python - funcion - Cuando llamo a super() en una clase derivada, ¿puedo pasar yo mismo.__ class__?
funcion super python (2)
No, no puedes. La llamada a super()
necesita saber de qué clase forma parte el método, para buscar en las clases base un método anulado.
Si pasa en self.__class__
(o mejor aún, type(self)
), entonces a super()
se le da un punto de partida incorrecto para buscar métodos, y terminará llamando a su propio método de nuevo .
Véalo como un puntero en la lista de clases que forman la secuencia Orden de resolución de método. Si pasa el type(self)
, el puntero se referirá a cualquier subclase en lugar del punto inicial original.
El siguiente código conduce a un error de recursión infinito:
class Base(object):
def method(self):
print ''original''
class Derived(Base):
def method(self):
print ''derived''
super(type(self), self).method()
class Subclass(Derived):
def method(self):
print ''subclass of derived''
super(Subclass, self).method()
Manifestación:
>>> Subclass().method()
subclass of derived
derived
derived
derived
<... *many* lines removed ...>
File "<stdin>", line 4, in method
File "<stdin>", line 4, in method
File "<stdin>", line 4, in method
RuntimeError: maximum recursion depth exceeded while calling a Python object
porque type(self)
es Subclass
, no Derived
, en Derived.method()
.
En el ejemplo, el MRO para la Subclass
es [Subclass, Derived, Base]
, y super()
necesita saber dónde comenzar la búsqueda de cualquier método anulado. Al usar type(self)
le dices que comience en Subclass
, por lo que encontrará Derived.method()
next, que es donde comenzamos.
Esta pregunta ya tiene una respuesta aquí:
- Cómo evitar la recursión infinita con super ()? 1 respuesta
Recientemente descubrí (a través de StackOverflow) que para llamar a un método en una clase base debería llamar:
super([[derived class]], self).[[base class method]]()
Está bien, funciona. Sin embargo, a menudo me encuentro copiando y pegando entre clases cuando hago un cambio y con frecuencia me olvido de arreglar el argumento de la clase derivada para la función super ().
Me gustaría evitar tener que recordar cambiar el argumento de la clase derivada. ¿Puedo simplemente usar self.__class__
como el primer argumento de la función super ()?
Parece que funciona pero ¿hay buenas razones por las que no debería hacer esto?
self.__class__
podría no ser una subclase, sino una clase de nieto o menor, lo que lleva a un ciclo de rompimiento de pila.