类中定义的__getattr__方法时,id(__ getattribute__)函数返回的值不同

时间:2018-10-28 17:05:41

标签: python python-3.x id

如下所示,当定义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

1 个答案:

答案 0 :(得分:1)

每当您进行instance.method查找时,总会得到一个新的绑定方法对象。这种绑定是self参数传递给函数的方式(方法的查找将实例绑定到类字典中的函数)。

是否获得具有相同id的方法与Python如何计算这些id值无关。从id获得的值被保证是唯一的,但是仅在同时存在的对象之间。垃圾回收一个对象后,可能会创建另一个具有相同ID的对象。

CPython根据对象的内存地址生成id。相同的内存将经常在不同的时间重用于不同的绑定方法对象,因为缓存内存比使用新内存要快得多。正是这种重用发生时,才是实现细节。其他Python解释器(例如PyPy或Jython),甚至其他版本的CPython都可能以不同的方式或根本没有这样做。您永远不要依赖此行为的特定详细信息(或从id获取的特定值的任何其他详细信息)。您应该依赖id 事情是,对于同时存在的对象来说,它总是不同的。

我怀疑改变类中的方法数量会改变id重用的行为是偶然的。也许是有原因的(例如,类机制中的某项正在某处创建一个额外的绑定方法对象),但是知道确切的原因并不能带来任何好处。这些细节将是非常特定于实现的,因此您永远不应依赖它们,就像这样做一样,它们可能会更改并破坏您的代码,而不会发出警告。