2012-02-01 7 views
3

、ライターはが作成、運営されてどのようにユーザー定義の方法を説明する努力の多くを過ごした:(http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchyを参照してください。おそらく、そのクラスのインスタンスを介してクラス()の属性 を取得するときに 属性がユーザ定義関数オブジェクトである場合Pythonのデータモデルドキュメント:参照の<strong>データモデル</strong>に結合していないユーザー定義のメソッドオブジェクトとクラスメソッドオブジェクト

ユーザ定義のメソッドオブジェクトは、作成することができる)ダウンロール、バインドされていないユーザー定義の メソッドオブジェクト、またはクラスメソッドオブジェクト属性が ユーザー定義メソッドオブジェクトである場合、元のメソッドオブジェクトに格納されているクラスと同じか、派生クラスの クラスである場合にのみ、新しいメソッドオブジェクトが作成されます;そうでなければ、 元のメソッドオブジェクトがそのまま使用されます。

ので、クラスメソッドオブジェクト結合していないユーザー定義のメソッドオブジェクト間と違いは何ですか?

答えて

6

"ユーザ"の観点から見ると、Pythonのクラスメソッドは、最初のパラメータとしてクラスのインスタンスを受け取る「通常の」メソッドとは異なり、そのクラスを最初のパラメータとして受け取るメソッドです。 selfと呼ばれます。

そのクラスのインスタンスではなく、クラスから「通常の」メソッドを取得すると、関数のラッパーであるオブジェクトが自動的に追加されないクラス自体、または呼び出されたときの最初のパラメータとしてのインスタンスのいずれかです。したがって、「バインドされていないメソッド」を呼び出す場合は、そのクラスのインスタンスを最初のパラメータとして手動で渡す必要があります。手動でクラスメソッドを呼び出した場合、他の一方で、クラスはあなたのための最初のパラメータとして記入されて

:多かれ少なかれ、このようなものです何が起こるのか、フードの下

>>> class A(object): 
... def b(self): 
...  pass 
... @classmethod 
... def c(cls): 
...  pass 
... 
>>> A.b 
<unbound method A.b> 
>>> A.c 
<bound method type.c of <class '__main__.A'>> 
>>> A.c() 
>>> A.b() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method b() must be called with A instance as first argument (got nothing instead) 
>>> 

- 」で新しいスタイルクラス ":

クラス本体を定義するとき、メソッドは単なる普通の関数です - クラス本体が終了すると、Pythonはクラスのメタクラス(通常は組み込みのtype)を呼び出し、パラメータとして渡します名前、基本クラス、およびクラス本体の辞書。この呼び出しはクラスを生成します。これは、Pythonではオブジェクトであるため、クラスです。

ここで、Pythonには属性アクセスをカスタマイズするための素晴らしい方法がいくつかあります。いわゆる「記述子」です。記述子は、__get__という名前のメソッド(または__set__または__del__)を定義するオブジェクトですが、ここではそれらは気にしません。 Pythonでクラスまたはオブジェクトの属性にアクセスすると、その属性によって参照されるオブジェクトが返されます(クラス属性であり、オブジェクトが記述子である場合を除く)。その場合、オブジェクト自体を返す代わりに、Pythonはそのオブジェクトに対して__get__メソッドを呼び出し、代わりにその結果を返します。たとえば、propertyビルトインは、__set__,__get__および__del__の両方を適切に実装するクラスに過ぎません。

ここで、属性が取得されたとき、その本体上の関数(またはデータモデルの状態としてのクラスメソッドまたは非バインドメソッド)が__get__メソッドを持ち、それが記述子になります。基本的には、各属性で、関数本体で定義されている関数として名前を付けられたオブジェクトを取得するためのアクセス権が、その関数の周りに新しいオブジェクトを作成する記述子 - 呼び出されると最初のパラメータが自動的に埋め込まれるオブジェクト - 例えば、methodです。

例:

>>> class B(object): 
... def c(self): 
...  pass 
... print c 
... 
<function c at 0x1927398> 
>>> print B.c 
<unbound method B.c> 
>>> b = B() 
>>> b.c 
<bound method B.c of <__main__.B object at 0x1930a10> 

あなたは関数オブジェクトを取得する場合、メソッドオブジェクトに変換せずに、あなたが記述をトリガしませんクラスの__dict__属性を介して、そうすることができます。

>>> B.__dict__["c"] 
<function c at 0x1927398> 
>>> B.__dict__["c"].__get__ 
<method-wrapper '__get__' of function object at 0x1927398> 
>>> B.__dict__["c"].__get__(b, B) 
<bound method B.c of <__main__.B object at 0x1930a10>> 
>>> B.__dict__["c"].__get__(None, B) 
<unbound method B.c> 

「クラスメソッド」は、組み込み関数で明示的に装飾された異なるタイプのオブジェクトですclassmethod - __get__が呼び出されたときに返されるオブジェクトは、origiコール時に最初のパラメータとしてclsを入力する関数です。

+0

したがって、バインドされていないメソッドを「インスタンスのメソッド」とし、クラスメソッドを「クラスのメソッド」とします。 – Determinant

+0

つまり、クラスから直接バインドされていないメソッドを呼び出すと、このメソッドを呼び出すには、最初にオブジェクトを作成してからメソッド "from"オブジェクトを呼び出す必要があります。クラスから直接メソッドを呼び出す場合は、デコレータ@staticmethodを使用してください。 – Denis

+0

@Denisよく装飾されたメソッド'@ classmethod'を使って、クラスへのバインドメソッドと言うことができますか? – Determinant

関連する問題