2012-04-22 7 views
14

Ich habe die folgende Basisklasse und Unterklasse:Python Klassenvererbung: Attribute: ‚[SubClass]‘ Objekt hat kein Attribut ‚xxx‘

class Event(object): 
    def __init__(self, sr1=None, nr1=None, foo=None, foobar=None, nr2=None, sr2=None, flag = False): 
     self.sr1 = sr1 
     self.nr1 = nr1 
     self.foo = foo 
     self.foobar = foobar 
     self.nr2 = nr2 
     self.sr2 = sr2 
     self.flag = flag 
     self.state = STATE_NON_EVENT 

    def state_name(self): 
     return STATE_NAMES[self.state] 

    def __repr__(self): 
     return '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 

    def __repr__(self): 
     return "Type Two event (Level @: {0:.2f})".format(self.sr1) 

Weiter in meinem Code, ich bin Inspektion eine Instanz eines TypeTwoEvent-Klasse, die nach einem Feld sucht, von dem ich weiß, dass es in der Basisklasse vorhanden ist - ich erwartete, dass es standardmäßig den Wert None hat. Allerdings wirft mein Code die folgende Ausnahme:

AttributeError: 'TypeTwoEvent' object has no attribute 'foobar'

Ich habe den Eindruck, dass die Basisklasse Felder, die von der Unterklasse geerbt werden würden und dass eine Instanz einer Unterklasse zu schaffen wird die Basisklasse instanziiert (und damit Aufruf seines Konstruktors) ...

Was fehlt mir hier ?. Warum hat TypeTwoEvent kein Foobar-Attribut - wenn die Basisklasse, von der es abgeleitet ist, ein Foobar-Attribut hat?

+1

Wie unten erwähnt, müssen Sie explizit angeben, dass die Oberklassen ebenfalls initialisiert werden sollen. Aber __take care__: Wenn Sie mehrere Vererbung haben, dann wird dies sehr heikel. – katrielalex

Antwort

15

sollte Ihre Unterklasse sein:

class TypeTwoEvent(Event): 

    def __init__(self, level=None, *args, **kwargs): 
     super(TypeTwoEvent, self).__init__(*args, **kwargs) 
     self.sr1 = level 
     self.state = STATE_EVENT_TWO 

    def __repr__(self): 
     return "Type Two event (Level @: {0:.2f})".format(self.sr1) 

Da Sie die __init__ Methode überschreiben, so dass Sie die übergeordnete Methode aufrufen müssen, wenn Sie das übergeordnete Verhalten passieren soll.

Denken Sie daran, __init__ ist keine besondere Methode trotz seines seltsamen Namens. Es ist nur die Methode, die automatisch aufgerufen wird, nachdem das Objekt erstellt wurde. Ansonsten ist es eine gewöhnliche Methode, und es gelten die üblichen Vererbungsregeln.

super(ClassName, self).__init__(arguments, that, goes, to, parents) 

ist die Syntax zum Aufrufen der übergeordneten Version der Methode.

Für *args und **kwargs, sondern sorgt nur fangen wir alle weiteren Argumente zu __init__ weitergegeben und an die übergeordnete Methode übergeben, wie Sie Kind Methodensignatur nicht tat es und die Eltern müssen diese Argumente arbeiten.

+0

Danke für die Bearbeitung Chris. Ich bin Franzose, und ich mache diese Verwirrung zwischen "es ist" und "es" ziemlich häufig. Nicht, dass ich die Bedeutungen verwechsle, aber ich lernte die Sprache sprechen, dafür ist es (;-)) einfach, einen Ton für einen anderen in meinem Kopf auszutauschen. –

1

Sie müssen die Methode __init__ der Basisklasse von der __init__-Methode der geerbten Klasse aufrufen.

Siehe here für wie dies zu tun ist.

2

Wenn die Instanz erstellt wird, wird die Methode __init__ aufgerufen. In diesem Fall ist das TypeTwoEvent.__init__. Superklassenmethoden werden nicht automatisch aufgerufen, da dies immens verwirrend wäre.

Sie sollten Event.__init__(self, ...) von TypeTwoEvent.__init__ anrufen (oder super verwenden, aber wenn Sie nicht damit vertraut sind, lesen Sie es zuerst, damit Sie wissen, was Sie tun).

2

Sie überschreiben den Konstruktor (__init__) der übergeordneten Klasse. Um es zu erweitern, müssen Sie den Konstruktor des übergeordneten Elements explizit mit einem Aufruf super() aufrufen.

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 

Beachten Sie, dass der super Anruf nicht immer an der Spitze der __init__ Methode in der Unterklasse. Der Standort hängt von Ihrer Situation und Ihrer Logik ab.

0

Ich hatte auch ein Problem mit diesem, aber ich habe super().__init__() auf der Unterseite meiner abgeleiteten Klasse putted und das ist, warum es nicht funktioniert. Weil ich versuche, Attribute zu verwenden, die nicht initialisiert sind.

Verwandte Themen