Se encontró una manera más corta de hacer super(B, self).test()
->bubble()
desde abajo.
(Funciona con herencia múltiple, no requiere argumentos, correcly comporta con sub-clases)
La solución fue usar inspect.getmro(type(back_self))
(donde back_self
es una self
de destinatario de la llamada), a continuación, iterar como cls
con method_name in cls.__dict__
y verificar que la referencia de código que tenemos es la de esta clase (realizada en la función anidada find_class_by_code_object(self)
).
bubble()
se puede extender fácilmente con *args, **kwargs
.
import inspect
def bubble(*args, **kwargs):
def find_class_by_code_object(back_self, method_name, code):
for cls in inspect.getmro(type(back_self)):
if method_name in cls.__dict__:
method_fun = getattr(cls, method_name)
if method_fun.im_func.func_code is code:
return cls
frame = inspect.currentframe().f_back
back_self = frame.f_locals['self']
method_name = frame.f_code.co_name
for _ in xrange(5):
code = frame.f_code
cls = find_class_by_code_object(back_self, method_name, code)
if cls:
super_ = super(cls, back_self)
return getattr(super_, method_name)(*args, **kwargs)
try:
frame = frame.f_back
except:
return
class A(object):
def test(self):
print "A.test()"
class B(A):
def test(self):
# instead of "super(B, self).test()" we can do
bubble()
class C(B):
pass
c = C()
c.test() # works!
b = B()
b.test() # works!
Si alguien tiene una idea mejor, escuchemosla.
Error conocido: (gracias doublep) If C.test = B.test
-> "infinite" recursion. Aunque parece poco realista que la clase infantil tenga realmente un método, ha sido =
'ed de uno de los padres.
Bug2 Conocido: (doublep gracias) decoradas métodos no funcionará (probablemente irreparable, ya que devuelve un decorador de cierre) ... proble decorador fijo con for _ in xrange(5)
: frame = frame.f_back
... - se encargará de hasta 5 decoradores, aumente si es necesario. ¡Me encanta Python!
El rendimiento es 5 veces peor que super()
llamada, pero estamos hablando de 200K llamadas frente a un millón de llamadas por segundo, si esto no está en sus bucles más ajustados, no hay razón para preocuparse.
Si puedo preguntar ... ¿para qué necesita esto? Porque casi no creo que algo así pueda ser el mejor método para nada. – Wolph
Estoy tratando de simplificar haciendo 'super (B, self) .test()' para usuarios con algún tipo de llamada 'bubble()' simple. En realidad, ya encontré la manera. –
¿No podría hacer 'super (self .__ class__, self) .test()'? – Wolph