J'ai la classe de base et la sous-classe suivantes:
class Event(object):
def __init__(self, sr1=None, foobar=None):
self.sr1 = sr1
self.foobar = foobar
self.state = STATE_NON_EVENT
# Event class wrappers to provide syntatic sugar
class TypeTwoEvent(Event):
def __init__(self, level=None):
self.sr1 = level
self.state = STATE_EVENT_TWO
Plus loin dans mon code, j'inspecte une instance d'une classe TypeTwoEvent, en recherchant un champ que je connais qui existe dans la classe de base - je m'attendais à ce que sa valeur par défaut soit Aucune. Cependant, mon code soulève l'exception suivante:
AttributeError: l'objet 'TypeTwoEvent' n'a pas d'attribut 'foobar'
J'avais l'impression que les champs de la classe de base seraient hérités par la sous-classe et que la création d'une instance d'une sous-classe instancierait la classe de base (et invoquerait donc son constructeur) ...
Qu'est-ce que j'oublie ici?. Pourquoi TypeTwoEvent
ne possède-t-il pas d'attribut foobar
- lorsque la classe de base à partir de laquelle elle est dérivée a un attribut foobar
?
Votre sous-classe devrait être:
class TypeTwoEvent(Event):
def __init__(self, level=None, *args, **kwargs):
super(TypeTwoEvent, self).__init__(*args, **kwargs)
self.sr1 = level
self.state = STATE_EVENT_TWO
Comme vous substituez la méthode __init__
, vous devez donc appeler la méthode parent si vous souhaitez que le comportement parent se produise.
Rappelez-vous, __init__
n'est pas une méthode spéciale, malgré son nom étrange. C'est juste la méthode appelée automatiquement après la création de l'objet. Sinon, c'est une méthode ordinaire, et les règles d'héritage ordinaires s'appliquent.
super(ClassName, self).__init__(arguments, that, goes, to, parents)
est la syntaxe pour appeler la version parente de la méthode.
Pour *args
et **kwargs
, cela garantit simplement que nous capturons tous les arguments supplémentaires passés à __init__
et les transmettons à la méthode parent, car la signature de votre méthode enfant ne l’a pas fait et que le parent a besoin de ces arguments pour fonctionner.
Vous remplacez le constructeur (__init__
) de la classe parente. Pour l'étendre, vous devez appeler explicitement le constructeur du parent avec un appel super()
.
class TypeTwoEvent(Event):
def __init__(self, level=None, **kwargs):
# the super call to set the attributes in the parent class
super(TypeTwoEvent, self).__init__(**kwargs)
# now, extend other attributes
self.sr1 = level
self.state = STATE_EVENT_TWO
Notez que l'appel super
est not toujours en haut de la méthode __init__
dans votre sous-classe. Son emplacement dépend de votre situation et de votre logique.
Lorsque l'instance est créée, sa méthode __init__
est appelée. Dans ce cas, il s'agit de TypeTwoEvent.__init__
. Les méthodes de superclasse ne seront pas appelées automatiquement car cela créerait une grande confusion.
Vous devriez appeler Event.__init__(self, ...)
à partir de TypeTwoEvent.__init__
(ou utiliser super
, mais si vous ne le connaissez pas, lisez-le d'abord pour que vous sachiez ce que vous faites).
Vous devez appeler la méthode __init__
de la classe de base à partir de la méthode __init__
de la classe héritée.
Voir ici pour savoir comment faire cela.
Cela me pose également problème, mais j’ai mis super().__init__()
en bas de ma classe dérivée et c’est pourquoi cela ne fonctionne pas. Parce que j'essaie d'utiliser des attributs qui ne sont pas initialisés.