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.