106

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)
4

6 に答える 6

76
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
于 2009-06-07T02:23:02.750 に答える
9

ポイントを逃していたことを指摘してくれた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 ソリューションは同じ結果を返します。アレックスのアプローチが使用できる限り、私はこれの代わりにそれを使用します。

于 2012-11-29T14:38:10.637 に答える
2

パイソン3

非常に簡単な方法で解決しました:

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

これは与える

'FooClass.foo_method'

ドットを分割して、クラスと関数名を別々に取得します

于 2020-09-17T08:07:40.940 に答える
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()更新: 実際にfrom を呼び出してrun_method()(それは精神ではありませんか?)、すべての引数を変更せずにメソッドに渡します。

PS: この回答は、質問に直接回答するものではありません。私見には、どのクラスがメソッドを定義したかを知りたい理由が2つあります。1 つ目は、デバッグ コード (例外処理など) でクラスを指摘することです。2 つ目は、メソッドが再実装されているかどうかを判断することです (ここで、メソッドはプログラマによって実装されることを意図したスタブです)。この答えは、その2番目のケースを別の方法で解決します。

于 2014-10-15T20:44:40.847 に答える