関数は記述子として実装されます。ドキュメントを引用するには:
一般に、記述子は「バインディング動作」を持つオブジェクト属性であり、その属性アクセスは記述子プロトコルのメソッドによってオーバーライドされます。それらのメソッドは、、、__get__()
および__set__()
です__delete__()
。これらのメソッドのいずれかがオブジェクトに対して定義されている場合、それは記述子と呼ばれます。
アイデアは、メソッドが属性がどのよう__get__
にフェッチされたかを識別できるようにすることです。次の簡単な例を考えてみましょう。
>>> class Descriptor(object):
... def __get__(self, obj, type=None):
... print '__get__(%r, %r)' % (obj, type)
...
>>> class A(object):
... desc = Descriptor()
...
>>> A.desc
__get__(None, <class '__main__.A'>)
>>> A().desc
__get__(<__main__.A object at 0x020F5B50>, <class '__main__.A'>)
ご覧のとおり、__get__
ドキュメントで説明されているように、obj
パラメーターにより、クラスまたはインスタンスを介した属性アクセスを区別できます。関数属性にアクセスするときに、同じメカニズムを Python の内部で使用して、バインドされたメソッドまたはバインドされていないメソッドを返すことができます。
実際には:
>>> class A:
... def f(self):
... pass
...
>>> A.f.__get__(None, A)
<unbound method A.f>
>>> A.f.__get__(A(), A)
<bound method A.f of <__main__.A instance at 0x022082D8>>
これはすべて Python 2.x の例ですが、私が知る限り、バインドされていないメソッドが通常の関数であることを除いて、Python 3.x でも同じように機能します。