jsa*_*sau 22 python integer cpython
我id最近在摆弄并意识到(c?)Python做了一些非常明智的事情:它确保小的int总是有相同的id.
>>> a, b, c, d, e = 1, 2, 3, 4, 5
>>> f, g, h, i, j = 1, 2, 3, 4, 5
>>> [id(x) == id(y) for x, y in zip([a, b, c, d, e], [f, g, h, i, j])]
[True, True, True, True, True]
Run Code Online (Sandbox Code Playgroud)
但后来我想知道数学运算的结果是否也是如此.原来它是:
>>> nines = [(x + y, 9) for x, y in enumerate(reversed(range(10)))]
>>> [id(x) == id(y) for x, y in nines]
[True, True, True, True, True, True, True, True, True, True]
Run Code Online (Sandbox Code Playgroud)
好像它开始在n = 257失败...
>>> a, b = 200 + 56, 256
>>> id(a) == id(b)
True
>>> a, b = 200 + 57, 257
>>> id(a) == id(b)
False
Run Code Online (Sandbox Code Playgroud)
但有时即使数字较大,它仍然有效:
>>> [id(2 * x + y) == id(300 + x) for x, y in enumerate(reversed(range(301)))][:10]
[True, True, True, True, True, True, True, True, True, True]
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?python是如何做到这一点的?
Dun*_*can 18
你陷入了一个并不罕见的陷阱:
id(2 * x + y) == id(300 + x)
Run Code Online (Sandbox Code Playgroud)
这两个表达式2 * x + y并300 + x没有重叠的生命周期.这意味着Python可以计算左侧,获取其id,然后在计算右侧之前释放整数.当CPython释放一个整数时,它将它放在一个释放的整数列表中,然后在下次需要时将其重新用于另一个整数.因此,即使计算结果非常不同,您的ID也会匹配:
>>> x, y = 100, 40000
>>> id(2 * x + y) == id(300 + x)
True
>>> 2 * x + y, 300 + x
(40200, 400)
Run Code Online (Sandbox Code Playgroud)
Dae*_*yth 17
Python保留了int一定数量的对象池.当您在该范围内创建一个时,您实际上会获得对预先存在的引用的引用.我怀疑这是出于优化原因.
对于该池范围之外的数字,只要您尝试创建一个新对象,就会出现这种情况.
$ python
Python 3.2 (r32:88445, Apr 15 2011, 11:09:05)
[GCC 4.5.2 20110127 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = 300
>>> id(x)
140570345270544
>>> id(100+200)
140570372179568
>>> id(x*2)
140570345270512
>>> id(600)
140570345270576
Run Code Online (Sandbox Code Playgroud)
PyObject*PyInt_FromLong(long ival)返回值:新引用.创建一个值为ival的新整数对象.
当前实现为-5到256之间的所有整数保留一个整数对象数组,当您在该范围内创建一个int时,实际上只返回对现有对象的引用.因此应该可以更改值1.我怀疑在这种情况下Python的行为是未定义的.:-)
强调我的
| 归档时间: |
|
| 查看次数: |
849 次 |
| 最近记录: |