`id` 函数、`is` 运算符、对象标识和用户定义方法 [重复]

问题描述 投票:0回答:2

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 数据模型 的描述有些有用。但这并没有真正让一切变得清晰。如果每次都重新构造用户定义的方法对象,为什么

id
函数会返回相同的整数?

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

python python-2.7 identity equality
2个回答
20
投票

id 函数的 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


8
投票

这是内存分配器工作原理的“简单”结果。 和案例很相似:

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

基本上Python不保证ID不会被重用——它只保证ID是唯一的只要对象还活着。 在这种情况下,传递给

id
的第一个对象在调用
id
后就死掉了,并且 (C)python 在创建第二个对象时重新使用该
id

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

© www.soinside.com 2019 - 2024. All rights reserved.