Python中“a is b”和“id(a)== id(b)”有什么区别?

时间:2010-05-25 15:39:52

标签: python identity

id()内置函数给出了......

  

一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。

is运算符代替......

  

对象标识

那么为什么有两个具有相同id但返回Falseis支票的对象呢?这是一个例子:

>>> class Test():
...   def test():
...     pass
>>> a = Test()
>>> b = Test()
>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

一个更令人不安的例子:(继续上述)

>>> b = a
>>> b is a
True
>>> b.test is a.test
False
>>> a.test is a.test
False

然而:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

1 个答案:

答案 0 :(得分:56)

>>> b.test is a.test
False
>>> a.test is a.test
False

每次查找时都会即时创建方法。函数对象(始终是同一个对象)实现descriptor protocol,其__get__创建绑定的方法对象。没有两个绑定方法通常是同一个对象。

>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

这个例子具有欺骗性。第一个结果只是巧合Truea.test创建绑定方法,并在计算id(a.test)后收集垃圾,因为没有任何引用它。 (请注意,您引用文档说明id对于此对象在其生命周期中是唯一且常量的“(强调我的)。)b.test 发生到与之前绑定的方法具有相同的ID,并允许它,因为现在没有其他对象具有相同的ID。

请注意,您应该很少使用is,甚至更少使用idid(foo) == id(bar)总是错的。


关于你的新例子,希望你能得到它现在所做的:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

在这种情况下,我们不会动态地从类上的函数自动绑定self和返回绑定方法对象。在这种情况下,您只需将函数存储为实例属性。查找没有什么特别的事情(只有在查找类属性时才会调用描述符),因此每次查找属性时,都会获得存储的原始对象。