関数は、def
ステートメントまたはによって作成されlambda
ます。Python 2では、関数がステートメントの本体内に現れるclass
(またはクラス構築呼び出しに渡される)と、その関数はバインドtype
されていないメソッドに変換されます。(Python 3にはバインドされていないメソッドがありません。以下を参照してください。)関数がクラスインスタンスでアクセスされると、バインドされたメソッドに変換され、インスタンスが最初のパラメーターとしてメソッドに自動的に提供されます。self
def f1(self):
pass
これf1
が関数です。
class C(object):
f1 = f1
今C.f1
はバインドされていないメソッドです。
>>> C.f1
<unbound method C.f1>
>>> C.f1.im_func is f1
True
type
クラスコンストラクターを使用することもできます。
>>> C2 = type('C2', (object,), {'f1': f1})
>>> C2.f1
<unbound method C2.f1>
f1
手動で非バインドメソッドに変換できます。
>>> import types
>>> types.MethodType(f1, None, C)
<unbound method C.f1>
バインドされていないメソッドは、クラスインスタンスへのアクセスによってバインドされます。
>>> C().f1
<bound method C.f1 of <__main__.C object at 0x2abeecf87250>>
アクセスは、記述子プロトコルを介した呼び出しに変換されます。
>>> C.f1.__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
これらを組み合わせる:
>>> types.MethodType(f1, None, C).__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf87310>>
または直接:
>>> types.MethodType(f1, C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
関数と非バインドメソッドの主な違いは、後者がバインドされているクラスを知っていることです。非バインドメソッドを呼び出すかバインドするには、そのクラスタイプのインスタンスが必要です。
>>> f1(None)
>>> C.f1(None)
TypeError: unbound method f1() must be called with C instance as first argument (got NoneType instance instead)
>>> class D(object): pass
>>> f1.__get__(D(), D)
<bound method D.f1 of <__main__.D object at 0x7f6c98cfe290>>
>>> C.f1.__get__(D(), D)
<unbound method C.f1>
関数と非バインドメソッドの違いはごくわずかであるため、Python3はその違いを取り除きます。Python 3では、クラスインスタンスの関数にアクセスすると、関数自体が提供されます。
>>> C.f1
<function f1 at 0x7fdd06c4cd40>
>>> C.f1 is f1
True
Python2とPython3の両方で、これら3つは同等です。
f1(C())
C.f1(C())
C().f1()
関数をインスタンスにバインドすると、最初のパラメーター(通常はself
)をインスタンスに固定する効果があります。したがって、バインドされたメソッドC().f1
は、次のいずれかと同等です。
(lamdba *args, **kwargs: f1(C(), *args, **kwargs))
functools.partial(f1, C())