获取定义方法的类

时间:2009-06-07 02:18:12

标签: python python-2.6 python-datamodel

如何获得在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)

6 个答案:

答案 0 :(得分:61)

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

答案 1 :(得分:7)

感谢Sr2222指出我错过了这一点......

这是经过纠正的方法,就像亚历克斯一样,但不需要导入任何东西。我不认为这是一个改进,除非有一个庞大的继承类层次结构,因为这个方法一旦找到定义类就会停止,而不是像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方法,我就会使用它而不是这个。

答案 2 :(得分:3)

我不知道为什么没有人提起这个问题,或者为什么最高答案有50个upvotes,当时它很慢,但你也可以做到以下几点:

def get_class_that_defined_method(meth):
    return meth.im_class.__name__

对于python 3,我相信这已经改变了,你需要调查.__qualname__

答案 3 :(得分:1)

我开始做一些有点相似的事情,基本上这个想法是在子类中实现或不实现基类中的方法时进行检查。事实证明我最初的方式,我无法检测中间类何时实际实现该方法。

我的解决方法实际上非常简单;设置方法属性并稍后测试其存在。这是对整个事情的简化:

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()(不是灵魂?)并让它将未修改的所有参数传递给方法。

P.S。:这个答案没有直接回答这个问题。恕我直言,有两个原因需要知道哪个类定义了一个方法;第一种是将指针指向调试代码中的类(例如在异常处理中),第二种是确定方法是否已经重新实现(其中方法是由程序员实现的存根)。这个答案以不同的方式解决了第二种情况。

答案 4 :(得分:1)

Python 3

以非常简单的方式解决它:

str(bar.foo_method).split(" ", 3)[-2]

这给

'FooClass.foo_method'

在点上分开以分别获取类和函数名称

答案 5 :(得分:0)

在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('.'):
    vals = vals[attr]
# vals is now the class Foo.Bar