python - clases - vistas genericas django




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

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.


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.





inheritance