2017-01-17 3 views
4

からコール可能ではありませんclassmethodsという概念をPythonで学んでいます。python classmethodsはクラス.__ dict__

class A(): 
    n=0 
    # object method 
    def func_o(self): 
     self.n += 1 
     print self.n 

    # well, class method 
    @classmethod 
    def func_c(cls): 
     cls.n += 1 
     print cls.n 

クラスのcallable()属性をチェックするとき、私はこの独特の出力と出くわした:

>>> [(k, callable(v)) for k,v in A.__dict__.items()] 
[('__module__', False), ('__doc__', False), ('func_o', True), ('func_c', False), ('n', False)] 

('func_o', True)クラス__dict__は、同様に('func_c', False)何らかの理由を検査したにもかかわらず。

誰かが説明できますか?

答えて

5

classmethodオブジェクトは関数オブジェクトではありません。それは呼び出し可能ではありません。

classmethodオブジェクトは、記述子です。記述子は、特定のインスタンスまたはクラスへのオブジェクトのバインドを容易にします。関数とプロパティも記述子です。バインディングはそれぞれメソッドまたはプロパティ値を生成します。 Python Descriptor How Toを参照してください。クラスのclassmethod記述子にアクセスする場合は、classmethod.__get__(None, cls)呼び出しがトリガーされ、バインドされたメソッド(呼び出されると、最初の引数として渡されたクラスオブジェクトで元の関数が呼び出されます)を生成します。

__dict__属性を使用してすべてのクラス属性にアクセスすると、記述子プロトコルをバイパスしているため、生の記述子オブジェクト自体が取得されます。

明示的classmethodオブジェクトのクラス上のオブジェクトにアクセスする(したがって、クラスオブジェクトにクラスメソッドをバインドしdescriptor.__get__(None, cls)呼び出しをトリガー)、手動で結合し、またはテスト:

>>> A.__dict__['func_c'] 
<classmethod object at 0x1018e6cc8> 
>>> A.__dict__['func_c'].__get__(None, A) # explicitly bind to a class 
<bound method classobj.func_c of <class __main__.A at 0x101c52328>> 
>>> callable(A.__dict__['func_c'].__get__(None, A)) 
True 
>>> A.func_c # trigger the protocol and bind to a class 
<bound method classobj.func_c of <class __main__.A at 0x101c52328>> 

ます。また、アクセスすることができます元の関数classmethodオブジェクトがラップする、__func__属性使用:

>>> A.__dict__['func_c'].__func__ 
<function func_c at 0x101c59668> 

あまりにも呼び出し可能、もちろん、自分自身です。

このすべてがstaticmethodオブジェクトにも適用されることに注意してください。 staticmethodオブジェクトは、バインドされると、元の関数を返します。

関連する問題