当您请求一个实例的函数属性时,您将获得一个 绑定方法 :一个可调用对象,该对象包装了在类中定义的函数,并将实例作为第一个参数传递。在Python
2.x中,当您请求类的属性(即函数)时,会得到一个类似的代理对象,称为 未绑定方法 :
>>> class A: m = lambda: None...>>> A.m<unbound method A.<lambda>>
这个特殊对象是在您需要时创建的,并且显然没有缓存在任何地方。那意味着当你做
>>> A.m is A.mFalse
您正在创建两个 不同的 未绑定方法对象,并测试它们的身份。
注意
>>> x = A.m>>> x is xTrue
和
>>> A.m.im_func is A.m.im_funcTrue
工作正常。(
im_func是未绑定方法对象包装的原始函数。)
顺便说一句,在Python 3.x中,它
C.m isC.m是True,因为(几乎没有意义的)未绑定方法代理对象已被完全删除,而您只获得了定义的原始函数。
这只是Python属性查找非常动态的一个示例:当您请求对象的属性时,可以运行任意Python来计算该属性的值。这是另一个测试失败的示例,其中的原因更加清楚:
>>> class ChangingAttribute(object):... @property... def n(self):... self._n += 1... return self._n...... def __init__(self):... self._n = 0...>>> foo = ChangingAttribute()>>> foo.n1>>> foo.n2>>> foo.n3>>> foo.n is foo.nFalse>>> foo.n6



