Pythonでメソッドを定義したクラスを取得するにはどうすればよいですか?私はポイントを逃した指摘してメソッドを定義したクラスを取得する
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
Pythonでメソッドを定義したクラスを取得するにはどうすればよいですか?私はポイントを逃した指摘してメソッドを定義したクラスを取得する
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
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
おかげSr2222 ...
ここで修正アプローチがあります:
私は「__main__.FooClass
」を印刷するには、次の例をしたいと思いますアレックスのようなものですが、何かを輸入する必要はありません。 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
アレックス・ソリューションは、同じ結果を返します。アレックスのアプローチが使用できる限り、私はこれの代わりにそれを使用します。
'Cls()。meth .__ self__'は' meth 'のその特定のインスタンスにバインドされている 'Cls'のインスタンスを提供します。 'Cls()。meth.im_class'に似ています。あなたが 'class SCls(Cls)'を持っているなら、 'SCls()。meth .__ self__'は' Clls'インスタンスではなく 'SCls'インスタンスを取得します。 OPが望んでいるのは 'Cls'を手に入れることです。それは@Alex MartelliのようにMROを歩くことによってのみ利用可能です。 –
@ sr2222そうです。私はアレックスのソリューションがよりコンパクトだとは思っていますが、私がすでに始めているように答えを修正しました。 – estani
輸入を避ける必要がある場合は良い解決策ですが、基本的にMROを再実装するだけなので、永遠に動作することは保証されません。 MROはおそらく同じままですが、Pythonの過去にはすでに変更されていましたが、再度変更された場合、このコードは微妙で広範なバグになります。 –
私はやや似たようなことをやり始めましたが、基本的には基本クラスのメソッドが実装されたかどうかをチェックすることでした。私が最初にやったやり方は、中間のクラスが実際にこのメソッドを実装していたときには検出できませんでした。
私の回避策は実際にはとても簡単でした。メソッドを設定し、後でその存在をテストします。ここでは全部の簡素化です:
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
UPDATE:実際に(?ということは精神ではありません)run_method()
からmethod()
を呼び出すと、それは方法に変更されていないすべての引数を渡すことがあります。
P .:この回答は直接質問に答えません。どのクラスがメソッドを定義したのかを知りたいのは2つの理由があります。 (例外ハンドリングのような)デバッグコードでクラスの指を指すことです.2番目は、メソッドが再実装されたかどうかを判断することです(メソッドはプログラマによって実装されることを意図したスタブです)。この答えは、その別の方法で別のケースを解決します。
私は、誰もこれを育てていない理由を知っていないか、それは地獄のように遅い場合、トップの答えは50 upvotesを持っていますが、あなたも行うことができる理由次のPython 3用
def get_class_that_defined_method(meth):
return meth.im_class.__name__
私はこれが変わったと信じて、.__qualname__
を調べる必要があります。
使用しているPythonのバージョンは? 2.2より前のバージョンでは、im_classを使用することができましたが、バインドされたselfオブジェクトのタイプを示すように変更されました。 –
お役立ち情報しかし私は2.6を使用しています。 –