Obtener clase que define el método
¿Cómo puedo obtener la clase que definió un método en Python?
Me gustaría que se imprimiera el siguiente ejemplo"__main__.FooClass
":
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
4 answers
import inspect
def get_class_that_defined_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__:
return cls
return None
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-20 19:44:30
Gracias Sr2222 por señalar que estaba perdiendo el punto...
Aquí está el enfoque corregido que es igual que el de Alex, pero no requiere importar nada. Sin embargo, no creo que sea una mejora, a menos que haya una gran jerarquía de clases heredadas, ya que este enfoque se detiene tan pronto como se encuentra la clase definitoria, en lugar de devolver toda la herencia como lo hace getmro
. Como se ha dicho, este es un muy escenario improbable.
def get_class_that_defined_method(method):
method_name = method.__name__
if method.__self__:
classes = [method.__self__.__class__]
else:
#unbound method
classes = [method.im_class]
while classes:
c = classes.pop()
if method_name in c.__dict__:
return c
else:
classes = list(c.__bases__) + classes
return None
Y el Ejemplo:
>>> class A(object):
... def test(self): pass
>>> class B(A): pass
>>> class C(B): pass
>>> class D(A):
... def test(self): print 1
>>> class E(D,C): pass
>>> get_class_that_defined_method(A().test)
<class '__main__.A'>
>>> get_class_that_defined_method(A.test)
<class '__main__.A'>
>>> get_class_that_defined_method(B.test)
<class '__main__.A'>
>>> get_class_that_defined_method(C.test)
<class '__main__.A'>
>>> get_class_that_defined_method(D.test)
<class '__main__.D'>
>>> get_class_that_defined_method(E().test)
<class '__main__.D'>
>>> get_class_that_defined_method(E.test)
<class '__main__.D'>
>>> E().test()
1
Alex solution devuelve los mismos resultados. Mientras se pueda usar el enfoque de Alex, lo usaría en lugar de este.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-30 13:04:15
No se por qué nadie ha mencionado esto o por qué la respuesta superior tiene 50 votos positivos cuando es lenta como el infierno, pero también puedes hacer lo siguiente:
def get_class_that_defined_method(meth):
return meth.im_class.__name__
Para python 3 creo que esto cambió y tendrá que mirar en .__qualname__
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-02 21:09:46
Empecé a hacer algo similar, básicamente la idea era comprobar cada vez que un método en una clase base se había implementado o no en una subclase. Resultó que la forma en que lo hice originalmente no pude detectar cuando una clase intermedia estaba implementando el método.
Mi solución para ello era bastante simple en realidad; establecer un atributo method y probar su presencia más tarde. He aquí una simplificación de todo:
class A():
def method(self):
pass
method._orig = None # This attribute will be gone once the method is implemented
def run_method(self, *args, **kwargs):
if hasattr(self.method, '_orig'):
raise Exception('method not implemented')
self.method(*args, **kwargs)
class B(A):
pass
class C(B):
def method(self):
pass
class D(C):
pass
B().run_method() # ==> Raises Exception: method not implemented
C().run_method() # OK
D().run_method() # OK
ACTUALIZACIÓN: En realidad llamar method()
de run_method()
(¿no es ese el espíritu?) y que pase todos los argumentos sin modificar al método.
P.d.: Esta respuesta no responde directamente a la pregunta. En mi humilde opinión, hay dos razones por las que uno querría saber qué clase definió un método; primero es señalar con el dedo a una clase en el código de depuración (como en el manejo de excepciones), y el segundo es determinar si el método ha sido re-implementado (donde el método es un stub destinado a ser implementado por el programador). Esta respuesta resuelve ese segundo caso de una manera diferente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-07 07:10:34