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

bad*_*adp 34 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
Run Code Online (Sandbox Code Playgroud)

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

>>> b = a
>>> b is a
True
>>> b.test is a.test
False
>>> a.test is a.test
False
Run Code Online (Sandbox Code Playgroud)

然而:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True
Run Code Online (Sandbox Code Playgroud)

Mik*_*ham 57

>>> b.test is a.test
False
>>> a.test is a.test
False
Run Code Online (Sandbox Code Playgroud)

每次查找时都会即时创建方法.函数对象(始终是同一个对象)实现描述符协议,__get__创建绑定的方法对象.没有两个绑定方法通常是同一个对象.

>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False
Run Code Online (Sandbox Code Playgroud)

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

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


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

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True
Run Code Online (Sandbox Code Playgroud)

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

  • *"每次查找时都会动态创建方法.函数对象(始终是同一个对象)实现描述符协议,其`__get__`创建绑定方法对象.通常没有两个绑定方法同一个对象."哈,这对我来说是新闻.太好了! (7认同)
  • 伙计,你太神奇了! (2认同)
  • 你是一个Python英雄. (2认同)