vistas genericas clases basadas python inheritance

genericas - Herencia de la clase Python: AttributeError: el objeto ''[SubClass]'' no tiene ningún atributo ''xxx''



vistas basadas en clases django (5)

Tengo la siguiente clase base y subclase:

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

Más adelante en mi código, estoy inspeccionando una instancia de una clase TypeTwoEvent, verificando si hay un campo que sé que existe en la clase base; esperaba que su valor predeterminado fuera el valor Ninguno. Sin embargo, mi código plantea la siguiente excepción:

AttributeError: el objeto ''TypeTwoEvent'' no tiene atributo ''foobar''

Tenía la impresión de que los campos de clase base serían heredados por la subclase y que crear una instancia de una subclase instanciará la clase base (y por lo tanto invocará a su constructor) ...

¿Que me estoy perdiendo aqui?. ¿Por qué TypeTwoEvent no tiene un atributo foobar , cuando la clase base de la que se deriva tiene un atributo foobar ?


Cuando se crea la instancia, se llama a su método __init__ . En este caso, eso es TypeTwoEvent.__init__ . Los métodos de superclase no serán llamados automáticamente porque eso sería muy confuso.

Debería llamar al Event.__init__(self, ...) desde TypeTwoEvent.__init__ (o use super , pero si no está familiarizado con él, lea primero para saber qué está haciendo).


Estás anulando el constructor ( __init__ ) de la clase padre. Para ampliarlo, debe llamar explícitamente al constructor del padre con una llamada 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

Tenga en cuenta que la super llamada no siempre está en la parte superior del método __init__ en su subclase. Su ubicación depende de su situación y lógica.


También he tenido problemas con esto, pero puse super().__init__() en la parte inferior de mi clase derivada y es por eso que no funciona. Porque trato de usar atributos que no están inicializados.


Tu subclase debe ser:

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

Como anula el método __init__ , debe llamar al método principal si desea que se produzca el comportamiento principal.

Recuerde, __init__ no es un método especial, a pesar de su nombre extraño. Es solo el método al que se llama automáticamente después de crear el objeto. De lo contrario, es un método ordinario, y se aplican las reglas de herencia ordinarias.

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

Es la sintaxis para llamar a la versión padre del método.

Para *args y **kwargs , solo garantiza que **kwargs todos los argumentos adicionales pasados ​​a __init__ y los __init__ al método primario, ya que la firma del método secundario no lo hizo y el padre necesita estos argumentos para funcionar.


__init__ llamar al método __init__ de la clase base desde el método __init__ de la clase heredada.

Vea here para here cómo hacer esto.