¿A qué clase está realmente llamando super (nombre de clase, instancia)?

He visto un montón de preguntas de orden de resolución del método de Python en Stack Overflow, muchas de las cuales tienen una excelente respuesta. Tengo uno que no me queda bien.

Cuando super(MyClassName, self).method_name , obtengo un tipo que no es devuelto por la clase principal (única). Poner la depuración en la clase padre muestra que no se ha ejecutado.

Me gustaría añadir algunos fragmentos de código, pero el código base es masivo. He estado en todas las clases que figuran en MyClassName.__mro__ (lo que nos dice cuál es el orden de resolución del método) y NINGUNA de ellas devuelve el tipo que estoy recibiendo. Así que la pregunta es …

¿Qué herramienta o atributo en Python puedo usar para averiguar qué código se está llamando en realidad, de modo que, si esto vuelve a suceder, puedo averiguar fácilmente cómo se está llamando? Terminé encontrando la solución, pero preferiría saber cómo enfrentarla de una manera menos laboriosa.

Puede utilizar, por ejemplo, inspect.getmodule , según su documentación:

Intenta adivinar en qué módulo se definió un objeto.

Un ejemplo simple, con a.py :

 class Parent(object): def method(self): return True 

y b.py :

 import inspect from a import Parent class Child(Parent): def method(self): parent_method = super(Child, self).method # get the parent method print "inherited method defined in {}".format( inspect.getmodule(parent_method), # and find out where it came from ) return parent_method() if __name__ == '__main__': Child().method() 

Ejecutando b.py da el resultado:

 Parent defined in  

Creo que podría estar confundido entre lo que es un método vinculado y cuál es el orden de resolución del método.

El método devuelto todavía cuenta como un método vinculado de la clase del objeto real, incluso si la función de la que deriva el método se encuentra en la clase principal. Esto se debe a que el método se ha vinculado a una instancia de la clase secundaria en lugar de a la clase primaria.

p.ej.

 class A: def f(self): return "A" class B(A): def g(self): return super().f class C(B): def f(self): return "C" c = C() method = cg() print(method) # prints > print(method()) # prints A 

En este caso, cg() devuelve la función Af enlazada a una instancia de C

Para encontrar la función real a la que llamará el método enlazado, simplemente examine el atributo __func__ :

 assert method.__func__ is Af