インスタンスへのバインドは、呼び出すときではなく、アクセスするときに行われます。 c.func
を実行するc.func = c.func
と、右側の属性アクセスはクラスによって処理されC
、バインドされたメソッドに評価されます。再割り当てc.func
してインスタンスに割り当てますが、すでにバインドされたメソッドであるため、動作は変わりません。
newfuncの例では、関数を定義して割り当てただけなので、インスタンスメソッドになりませんでした。インスタンスに直接割り当てるため、クラスはアクセスをインターセプトしてインスタンスメソッドでラップする機会がありません。
バインドされたメソッドはどこにでも割り当てることができ、それを取得したインスタンスにバインドされたままになります。次の例を参照してください。
>>> class C(object):
... def __init__(self, name):
... self.name = name
... def func(self, a):
... print("Called {0} with {1}".format(self.name, a))
>>> one = C("one")
>>> two = C("two")
>>> one.func(1)
Called one with 1
>>> two.func(1)
Called two with 1
>>> one.func2 = two.func
>>> one.func2(1)
Called two with 1
を割り当てたらone.func2 = two.func
、呼び出しは、ではなく、にone.func2
バインドされたインスタンスメソッドを呼び出すことに注意してください。これは、にアクセスしたときに、そのインスタンスにバインドされたメソッドを取得したためです。後でどこに割り当てるかは関係ありません。アクセスされたインスタンスにバインドされたままになります。two
one
two.func
バインドされていないメソッドに直接アクセスして別の場所に割り当てようとすると、メソッドがバインドされなかったため、TypeErrorが発生します。
>>> one.func3 = C.func
>>> one.func3(1)
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
one.func3(1)
TypeError: unbound method func() must be called with C instance as first argument (got int instance instead)
また、メソッドをクラスに追加すると、メソッドをクラスに追加する前にインスタンスが作成された場合でも、インスタンスで呼び出されたときに機能することに注意してください。以前と同じone
オブジェクトを保持して、私は次のことができます。
>>> def newFunc(self, a):
... print("Newfunc of {0} called with {1}".format(self.name, a))
>>> C.newFunc = newFunc
>>> one.newFunc(1)
Newfunc of one called with 1
質問に簡潔に答えるために、は、メソッドを持つクラスのインスタンスであり、それ自体にはインスタンス属性を持たないifc.func
にバインドされます。(同じ名前のインスタンス属性があった場合、それはクラス1をオーバーライドするため、クラスはメソッドをインスタンスにバインドするためにラッピングを実行できません。)c
c
func
c
func
c