【发布时间】:2021-07-15 22:50:01
【问题描述】:
感谢您的光临。
一开始,我很好奇将对象无限附加到数组时发生了什么。
所以,我试过了。
append 3 to array until id of array changed
我的想法如下。
有一天,python 应该将数组重新分配到另一个地方(在堆段中)。然后虚拟内存地址也会改变。根据cpython源码中的注释,
[python/bltinmodule.c-1201th line]
这保证在同时存在的对象中是唯一的。(CPython使用对象的内存地址。)
这是我的测试代码
arr = [3]
prev_id = id(arr[0])
print('arr_id:',hex(id(arr)))
print('prev_id:',hex(prev_id))
i = 1
import time
start = time.time()
while prev_id == id(arr[0]):
arr.append(3)
if(i % 10000000 == 0):
tmp = time.time()
print(hex(id(arr)), hex(id(arr[-1])), i, tmp-start)
start = tmp
i += 1
print(id(arr))
结果是……
prev_id: 0x7f9d00c9f5a0
0x7f9d00c9f5a0 0x7f9d00c9f5a0 10000000 3.284541130065918
0x7f9d00c9f5a0 0x7f9d00c9f5a0 20000000 3.3981776237487793
0x7f9d00c9f5a0 0x7f9d00c9f5a0 30000000 3.1428868770599365
0x7f9d00c9f5a0 0x7f9d00c9f5a0 40000000 3.3757195472717285
0x7f9d00c9f5a0 0x7f9d00c9f5a0 50000000 3.1835339069366455
...
0x7f9d00c9f5a0 0x7f9d00c9f5a0 840000000 3.0633106231689453
0x7f9d00c9f5a0 0x7f9d00c9f5a0 850000000 3.1029069423675537
0x7f9d00c9f5a0 0x7f9d00c9f5a0 860000000 3.124239921569824
0x7f9d00c9f5a0 0x7f9d00c9f5a0 870000000 3.0969555377960205
0x7f9d00c9f5a0 0x7f9d00c9f5a0 880000000 3.0810909271240234
0x7f9d00c9f5a0 0x7f9d00c9f5a0 890000000 3.090634346008301
0x7f9d00c9f5a0 0x7f9d00c9f5a0 900000000 3.079714298248291
0x7f9d00c9f5a0 0x7f9d00c9f5a0 910000000 3.051016092300415
(the program infinitely append '3' to the array until run out of memory.)
第三列和第四列的图(x: 10,000,000*append, y: time(s))
比较'append(3)'和'append(1234567)'
在 colab 中记录消息。好像有些东西被重新分配了
[2021.04.23编辑三张图]
通过图形,我们可以注意到图形是周期性指向的。我认为这是因为 python 重新分配。
- 我猜对了吗?
另外,我实际上想获取数组的虚拟内存地址。可能是这个(0x7f9d00c9f5a0) 是吧。
- 那么(虽然数组被重新分配了)为什么数组的id是一样的呢?
数组重新分配后如何获取虚拟内存地址?
【问题讨论】:
-
NOTHING 永远不会改变现有对象的 ID。任何在大小上增长(因此最终需要重新分配内存)的东西,例如一个列表,必然会将增长的部分作为一个单独的内存块,由 ID 所指的固定大小的块指向。无法从纯 Python 中确定该单独块的地址。
-
非常感谢杰森哈珀!顺便说一句,您能否深入解释一下“列表的增长部分必然会作为一个单独的内存块,由 ID 所指的固定大小的块所指向。”?
-
Python 列表对象本身不能在内存中移动(因为这会使对列表的所有现有引用无效)。但是列表数据必须能够在内存中移动(因为当列表增长时,通常不会有任何空间来扩展数据)。这不是唯一可以想到的解决方案,但将列表数据放在单独的内存块中肯定是最简单的解决方案。列表数据只有一个引用(在列表对象本身中),因此在需要重新分配时可以轻松更新。
-
非常感谢杰森哈珀!