当您访问c.func时,会发生对实例的绑定,而不是在您调用它时.当你执行c.func = c.func时,右侧的属性访问由类C处理并且对绑定方法进行评估.将它重新分配给c.func会将其分配给实例,但它已经是绑定方法,因此这不会改变行为.
在newfunc示例中,您刚刚定义了一个函数并对其进行了分配,因此它永远不会成为实例方法.由于您直接将其分配给实例,因此该类没有机会拦截访问并将其包装在instanceopthod中.
您可以在任何您喜欢的地方分配绑定方法,它仍然绑定到您获得它的实例.看这些例子:
>>> 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.func时,我得到了一个绑定到该实例的方法.我稍后分配它并不重要.它仍然与访问它的实例绑定.
如果直接访问未绑定方法并尝试将其分配到其他位置,则会得到TypeError,因为该方法从未绑定:
>>> one.func3 = C.func
>>> one.func3(1)
Traceback (most recent call last):
File "", line 1, in
one.func3(1)
TypeError: unbound method func() must be called with C instance as first argument (got int instance instead)
另请注意,如果将方法添加到类中,则在实例上调用时它将起作用,即使在将方法添加到类之前创建了实例也是如此.从以前保持相同的一个对象,我可以这样做:
>>> 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
为了简洁地回答你的问题,如果c是具有方法func的类的实例,则c.func绑定到c,并且c本身不具有实例属性func. (如果c确实具有相同名称的实例属性,那么它会覆盖第一类,因此类不会进行包装以将方法绑定到实例.)