如何获得在Python中定义方法的类?
我想要以下示例打印“ __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)
如何获得在Python中定义方法的类?
我想要以下示例打印“ __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)
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
__dict__
!有时__slots__
被使用。最好getattr
测试一下该方法是否在类中。
Python 3
,请参考此答案。
'function' object has no attribute 'im_class'
感谢Sr2222指出我错过了重点...
这是经过纠正的方法,就像Alex一样,但是不需要导入任何内容。但是,我认为这不是一种改进,除非存在巨大的继承类层次结构,因为一旦找到定义类,该方法就会停止,而不是像getmro
这样返回整个继承。如前所述,这是极不可能的情况。
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
和示例:
>>> 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解决方案返回相同的结果。只要可以使用Alex方法,我就会用它代替这一方法。
Cls().meth.__self__
只是为您提供的实例Cls
绑定到的特定实例meth
。类似于Cls().meth.im_class
。如果有class SCls(Cls)
,SCls().meth.__self__
将为您提供一个SCls
实例,而不是Cls
实例。OP想要得到的是Cls
,它看起来像@Alex Martelli一样只能通过MRO行走。
我不知道为什么没人能提起这个问题,或者为什么最慢的答案在地狱般缓慢的时候会有50次否决,但是您也可以执行以下操作:
def get_class_that_defined_method(meth):
return meth.im_class.__name__
对于python 3,我相信情况已经改变,您需要研究.__qualname__
。
在Python 3中,如果您需要实际的类对象,则可以执行以下操作:
import sys
f = Foo.my_function
vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]] # Gets Foo object
如果函数可以属于嵌套类,则需要进行以下迭代:
f = Foo.Bar.my_function
vals = vars(sys.modules[f.__module__])
for attr in f.__qualname__.split('.')[:-1]:
vals = vals[attr]
# vals is now the class Foo.Bar
我开始做一些类似的事情,基本上,我的想法是检查是否在基类中实现了方法,或者是否在子类中实现了方法。原来我的方式是我无法检测到中间类何时真正实现了该方法。
实际上,我的解决方法非常简单;设置方法属性并稍后测试其存在。这是整个过程的简化:
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
更新:实际method()
从run_method()
(不是精神吗?)进行并将其所有未修改的参数传递给该方法。
PS:此答案不能直接回答问题。恕我直言,有两个原因,一个是想知道哪个类定义了一个方法。首先是将手指指向调试代码中的类(例如,在异常处理中),其次是确定该方法是否已重新实现(其中method是应由程序员实现的存根)。这个答案以另一种方式解决了第二种情况。
用非常简单的方法解决了它:
str(bar.foo_method).split(" ", 3)[-2]
这给
'FooClass.foo_method'
在点上分割以分别获取类和函数名称