「ユーザー」の観点から見ると、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__
される元の関数のラッパーです。cls