如下所示,当定义id(a.__getattribute__)
方法时,__getattr__
返回不同的值。这是怎么发生的? (我的Python是v3.7.0)
class A():
def __getattribute__(self,key):
print(key)
return super().__getattribute__(key)
def f():
pass
def __getattr__(self,key):
print(key)
return super().__getattr__(key)
a=A()
print('id(a.__getattribute__)')
print(id(a.__getattribute__))
print(id(a.__getattribute__))
print(id(a.__getattribute__))
print(id(a.__getattribute__))
输出结果:
id(a.__getattribute__)
__getattribute__
44147656
__getattribute__
12643664
__getattribute__
44147656
__getattribute__
12643664
评论__getattr__
时:
...
## def __getattr__(self,key):
## print(key)
## return super().__getattr__(key)
...
输出结果:
id(a.__getattribute__)
__getattribute__
11005264
__getattribute__
11005264
__getattribute__
11005264
__getattribute__
11005264
答案 0 :(得分:1)
每当您进行instance.method
查找时,总会得到一个新的绑定方法对象。这种绑定是self
参数传递给函数的方式(方法的查找将实例绑定到类字典中的函数)。
是否获得具有相同id
的方法与Python如何计算这些id
值无关。从id
获得的值被保证是唯一的,但是仅在同时存在的对象之间。垃圾回收一个对象后,可能会创建另一个具有相同ID的对象。
CPython根据对象的内存地址生成id
。相同的内存将经常在不同的时间重用于不同的绑定方法对象,因为缓存内存比使用新内存要快得多。正是这种重用发生时,才是实现细节。其他Python解释器(例如PyPy或Jython),甚至其他版本的CPython都可能以不同的方式或根本没有这样做。您永远不要依赖此行为的特定详细信息(或从id
获取的特定值的任何其他详细信息)。您应该依赖id
的 事情是,对于同时存在的对象来说,它总是不同的。
我怀疑改变类中的方法数量会改变id
重用的行为是偶然的。也许是有原因的(例如,类机制中的某项正在某处创建一个额外的绑定方法对象),但是知道确切的原因并不能带来任何好处。这些细节将是非常特定于实现的,因此您永远不应依赖它们,就像这样做一样,它们可能会更改并破坏您的代码,而不会发出警告。