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

gkb*_*986 12 python identity equality python-2.7

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
Run Code Online (Sandbox Code Playgroud)

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

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

Mic*_*x2a 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
Run Code Online (Sandbox Code Playgroud)

......你会得到预期的价值False.


mgi*_*son 8

这是内存分配器工作方式的"简单"结果.它与案例非常相似:

>>> id([]) == id([])
True
Run Code Online (Sandbox Code Playgroud)

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

不要依赖于语言引用所允许的这种行为,但肯定不是必需的.