Python super () argumentos: ¿por qué no super (obj)?

Estoy tratando de entender cuándo y cómo usar super () en Python correctamente (ya sea 2.7.x o 3.x)

en >>> help(super) el intérprete me dice cómo llamarlo:

 class super(object) | super(type) -> unbound super object | super(type, obj) -> bound super object; requires isinstance(obj, type) | super(type, type2) -> bound super object; requires issubclass(type2, type) 

Entiendo que en Python3.x ahora es posible usar de forma super () dentro de una definición de clase, pero no entiendo por qué no es posible super(obj) . O super(self) dentro de una definición de clase.

Sé que debe haber una razón para ello, pero no puedo encontrarlo. Para mí, esas líneas son equivalentes a super(obj.__class__, obj) o super(self.__class__, self) y esas funcionan bien?

Creo que solo teclear super(obj) sería un buen atajo incluso en Python 3.x.

La forma de dos argumentos solo se necesita en Python 2. La razón es que self.__class__ siempre se refiere a la clase “hoja” en el árbol de herencia, es decir, la clase más específica del objeto, pero cuando se llama super necesita decirle qué implementación se está invocando actualmente, para que pueda invocar la siguiente en el árbol de herencia.

Supongamos que usted tiene:

 class A(object): def foo(self): pass class B(A): def foo(self): super(self.__class__, self).foo() class C(B): def foo(self): super(self.__class__, self).foo() c = C() 

Tenga en cuenta que c.__class__ es C , siempre. Ahora piensa en lo que pasa si llamas a c.foo() .

Cuando llama a super(self.__class__, self) en un método de C, será como llamar a super(C, self) , que significa “llamar a la versión de este método heredado por C”. Eso llamará B.foo , que está bien. Pero cuando llamas super(self.__class__, self) desde B, sigue siendo como llamar super(C, self) , porque es el mismo self , por lo que self.__class__ sigue siendo C El resultado es que la llamada en B volverá a llamar a B.foo y se B.foo una recursión infinita.

Por supuesto, lo que realmente quieres es poder llamar super(classThatDefinedTheImplementationThatIsCurrentlyExecuting, self) , y eso es efectivamente lo que hace Python 3 super() .

En Python 3, puedes hacer super().foo() y hace lo correcto. No me queda claro a qué te refieres con que super(self) es un atajo. En Python 2, no funciona por la razón que describí anteriormente. En Python 3, sería un “corte largo” porque en su lugar puedes usar simplemente super() .

Los usos super(type) y super(type1, type2) pueden seguir siendo necesarios ocasionalmente en Python 3, pero siempre fueron usos más esotéricos para situaciones inusuales.

Intentando una respuesta corta:

self.__class__ es siempre la clase real (“sub-más”) de su instancia de objeto, no necesariamente la clase deseada, ¡lo cual implementa la función!

Reemplace super(self.__class__, self) con super(__class__, self) y tiene razón dentro de una definición de método en Python 3, porque Python 3 proporciona la variable de celda mágica __class__ para la clase implementadora.

Y simplemente super() con cero argumentos ya es el atajo para super(__class__, self) en Python 3. Ver PEP3135 .

Python 2 no conoce __class__ ni el atajo de argumento cero super() .