Python实例函数id不一致

Gul*_*zar 3 python binding closures

请考虑以下事项

class A(object):
    def foo(self):
        pass


a = A()
# accessing a's foo seems consistent
init1 = a.foo
init2 = a.foo
assert init1 == init2
assert id(a.foo) == id(a.foo)

# Or is it?
foos= [a.foo for i in range(10)]
ids = [id(foo) for foo in foos]
for i, id_ in enumerate(ids):
    for j, id__ in enumerate(ids):
        if i != j:
            assert id_ != id__
Run Code Online (Sandbox Code Playgroud)

看来id(a.foo)可以等于id(a.foo)和不能等于id(a.foo),但我不明白什么时候相同,什么时候不同。

请解释一下这是怎么回事。

sj9*_*126 6

每次访问实例方法属性时都会发生函数到实例方法的转换,因此每次 id 都应该不同,至少在创建新对象的意义上是这样。(有关方法转换和描述符的详细信息,请参阅Python数据模型)

问题是这样做:

assert id(a.foo) == id(a.foo)
Run Code Online (Sandbox Code Playgroud)

有时,Python 垃圾收集器的工作速度非常快,即使在单个表达式中,两个不同的对象也可以具有相同的 id,因为该对象已经被回收一次id()

如果你这样做:

assert id(init1) == id(init2)
Run Code Online (Sandbox Code Playgroud)

你会发现它们实际上有不同的 id。


更新:解决为什么:和init1 == init2是方法包装器对象引用同一类中的相同函数的问题,因此方法包装器认为它们相等。Trueinit1init2__eq__()

  • @PeterWood:它在[Python数据模型](https://docs.python.org/3/reference/datamodel.html)中:“请注意,每次检索属性时都会发生从函数对象到实例方法对象的转换来自实例。” (2认同)