2016-09-14 20 views
0

私は2つのクラスがあります。メソッド本体から定義クラスを取得する方法は?

a = A() 
b = B() 
a.foo() 
b.foo() 

(つまり、これは予想される動作である)、これを生成します:

A 
A 

class A: 
    def foo(self): 
     print(<get the defining class>) 

class B(A): 
    pass 

は今、私はこれはというようなコードで<get the defining class>を交換する必要が

私はself.__class__.__name__を試しましたが、それはselfであるため、最後の呼び出しでは明らかにBを生成します。fac t、クラスBです。

私はメソッド本体(クラスメソッドではない)にいる場合、メソッドが定義されているクラスの名前はどのように取得できますか?

+0

私は混乱しています。 A&Aが間違っていて、A&Bがあなたが期待していないものであれば、実際に何を期待していますか? –

+0

@JonClementsいいえ、A&Aは正しいです。混乱を指摘してくれてありがとう。 – zegkljan

+1

右...「クラスC:def foo(self)#何でも」を実行すると、 'class D(B、C)'はどこに 'foo'が定義されていますか? –

答えて

2

これを実行する最も簡単な方法は、関数修飾名を使用することです:

class A: 
    def foo(self): 
     print(self.foo.__qualname__[0]) 

class B(A): 
    pass 

修飾名が定義されたクラスとcls_name.func_name形式の関数名で構成されています。 __qualname__[0]は、クラス名が1文字で構成されているため、ここに合っています。もちろんドットで分割して最初の要素self.foo.__qualname__.split('.')[0]を返すほうがよいでしょう。両方の場合

、結果は次のとおりです。

>>> a = A() 
>>> b = B() 
>>> a.foo() 
A 
>>> b.foo() 
A 

より堅牢なアプローチが__mro__を登ると機能type(self).fooごとにクラスの__dict__の内側に募集しています:

def foo(self): 
    c = [cls.__name__ for cls in type(self).__mro__ if getattr(type(self), 'foo', None) in cls.__dict__.values()] 
    print(c[0]) 

これは、もう少し複雑になりますが、同じ結果が得られます。

-1

私は、このロジックを各関数にハードコードしたくないと仮定しています。これは、例のコードで簡単に行うことができるからです。

printステートメントが常にこの動作を実行するメソッドの最初のステートメントである場合、可能な解決策の1つはデコレータを使用することです。

def print_defining_class(fn): 
    calling_class = fn.__qualname__.split('.')[0] 
    def decorated(*args, **kwargs): 
     print(calling_class) 
     return fn(*args, **kwargs) 
    return decorated 

class A: 
    @print_defining_class 
    def method(self): pass 

class B(A): pass 

A().method() # A 
B().method() # A 
関連する問題