Python 2.7中的`id`函数,`is`运算符,对象标识和用户定义的方法

时间:2014-09-15 15:03:07

标签: python python-2.7 identity equality

Python 2.7中的代码结果让我感到矛盾。 is运算符应该与对象标识一起使用,id也是如此。但是当我查看用户定义的方法时,他们的结果会有所不同。那是为什么?

py-mach >>class Hello(object):
...  def hello():
...    pass
...
py-mach >>Hello.hello is Hello.hello
False
py-mach >>id(Hello.hello) - id(Hello.hello)
0

我从Python data model的描述中发现以下摘录有点用处。但它并没有真正使一切清楚。如果每次重新构造用户定义的方法对象,为什么id函数返回相同的整数?

  

当获取类的属性(可能通过该类的实例),如果该属性是用户定义的函数对象,未绑定的用户定义的方法对象或类时,可以创建用户定义的方法对象方法对象。当属性是用户定义的方法对象时,仅当从中检索它的类与存储在原始方法对象中的类相同或派生类时,才会创建新的方法对象;否则,原始方法对象按原样使用。

2 个答案:

答案 0 :(得分:19)

id function州的Python文档:

  

返回对象的“标识”。这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。 具有非重叠生命周期的两个对象可能具有相同的id()值。

(强调我的)

执行id(Hello.hello) == id(Hello.hello)时,方法对象只是短暂创建,在第一次调用'id'后被视为“死”。由于对id的调用,您只需要Hello.hello在短时间内活着 - 足以获得ID。一旦你得到那个id,对象就死了,第二个Hello.hello可以重用那个地址,这使得它看起来好像两个对象具有相同的id。

这与执行Hello.hello is Hello.hello形成对比 - 两个实例都必须存活足够长时间才能相互比较,因此最终会有两个实时实例。

如果你改为尝试:

>>> a = Hello.hello
>>> b = Hello.hello
>>> id(a) == id(b)
False

...您将获得False的预期值。

答案 1 :(得分:8)

这是一个简单的"内存分配器如何工作的结果。它与案例非常相似:

>>> id([]) == id([])
True

基本上python并不能保证ID不会被重用 - 它只保证id是唯一的,只要对象是活着的。在这种情况下,传递给id的第一个对象在调用id之后死亡,而(C)python在创建第二个对象时重用id

不要依赖此行为,因为语言参考允许,但肯定不是必需