Tha*_*han 2 python object lifetime
id(t+t), id(t*2)
(42838592, 42838592)
(t+t) is (t*2)
False
Run Code Online (Sandbox Code Playgroud)
如果两个变量指向同一个对象'是',则运算符将返回true.但是第一行表示两者具有相同的id但是'is'运算符给出false值.
在第一个示例中,您的对象不会在时间上重叠:创建一个然后销毁,然后创建另一个具有相同ID的对象.
当你比较它们时is,你会抓住两个对象,所以它们得到不同的id.
正如Ned Batchelder 的回答和函数文档所解释的id:
生命周期不重叠的两个对象可能具有相同的
id()值。
并且这两个对象具有不重叠的生命周期。
它们是同一个元组表达式的一部分这一事实并没有改变这一点,因为它不是t+t并且t*2那是元组的一部分,它是id(t+t)and id(t*2)。因此,由 返回的这两个整数值id具有重叠的生命周期,但传递给的参数id没有。
理解这一点的一种方法是查看 CPython 如何编译代码:
>>> dis.dis('id(t+t), id(t*2)')
1 0 LOAD_NAME 0 (id)
2 LOAD_NAME 1 (t)
4 LOAD_NAME 1 (t)
6 BINARY_ADD
8 CALL_FUNCTION 1
10 LOAD_NAME 0 (id)
12 LOAD_NAME 1 (t)
14 LOAD_CONST 0 (2)
16 BINARY_MULTIPLY
18 CALL_FUNCTION 1
20 BUILD_TUPLE 2
22 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
所以,这就是发生的事情。(我将为 选择一个值t,比如说1000,只是为了让这更容易理解。)
id, 1000, 并被1000压入堆栈。BINARY_ADD2000在 location 处创建一个值42838592。id在该值上被调用并42838592在位置返回一个值,例如,42838616。42838592值不再在堆栈上并且未存储在任何地方,因此id的参数是对它的唯一引用,因此当它在函数末尾被取消时,它会立即被删除。id, 1000, 并被2压入堆栈。BINARY_MULTIPLY创建一个新2000对象。由于位置42838592刚刚返回到对象池,新值会重用该位置。id返回另一个42838592,这次是在位置,比如说,42838640。因此,这两个int值4283592并4283592具有重叠的生命周期(第一个与第二个重叠2000),两个2000s 不重叠。
最后,请注意,如果t是一个小数,
>>> t = 2
>>> (t+t) is (t*2)
True
Run Code Online (Sandbox Code Playgroud)
... 因为所有4值(除了在不寻常的情况下)都是对同一个对象的引用。
同时,如果t是一个常量而不是一个变量,1000+1000 is 1000*2可能是也可能不是真的,这取决于你的 CPython 版本,因为编译单元中常量折叠的工作方式。
所有这些都表明,试图真正利用两个相等的ints 是否是同一个对象几乎总是一个糟糕的主意。您应该关心这个问题的唯一原因是您是否正在尝试更多地了解 CPython 的内部结构。
当然,这都是 CPython 特有的。大多数其他 Python 解释器使用某种形式的垃圾收集器而不是引用计数,因此第一个2000不太可能在创建第二个之前被销毁。另外,并非所有人都使用像 CPython 这样的对象池。更不用说,id只要它们可以保证非重叠对象的唯一值,它们就可以做完全不同的事情。
PyPy 实际上通常会在这里返回相同的值——但这只是因为它首先折叠t+t并t*2放入同一个对象;尝试使用t+t和 t*3 and you'll get completely differentid`s。
| 归档时间: |
|
| 查看次数: |
545 次 |
| 最近记录: |