【发布时间】:2017-04-12 22:28:33
【问题描述】:
我必须从许多进程中访问一组大型且不可挑选的 Python 对象。因此,我想确保这些对象没有被完全复制。
根据this 和this 帖子中的 cmets,除非更改对象,否则不会复制对象(在 unix 系统上)。然而,引用一个对象会改变它的引用计数,然后它会被复制。
到目前为止这是正确的吗?由于我的担心是由于我的大对象的大小,如果这些对象的一小部分被复制,我没有问题。
为确保我正确理解所有内容并且没有意外发生,我实施了一个小型测试程序:
from multiprocessing import Pool
def f(arg):
print(l, id(l), object.__repr__(l))
l[arg] = -1
print(l, id(l), object.__repr__(l))
def test(n):
global l
l = list(range(n))
with Pool() as pool:
pool.map(f, range(n))
print(l, id(l), object.__repr__(l))
if __name__ == '__main__':
test(5)
在f 的第一行中,我希望id(l) 在所有函数调用中返回相同的数字,因为在id 检查之前列表没有改变。
另一方面,在f 的第三行中,id(l) 应该在每个方法调用中返回不同的数字,因为第二行中的列表已更改。
但是,程序输出让我感到困惑。
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[-1, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, -1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, -1, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, -1, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, -1] 139778408436488 <list object at 0x7f20b261d308>
[0, 1, 2, 3, 4] 139778408436488
f 的所有调用和行中的 id 都是相同的。即使列表在末尾保持不变(如预期的那样)也是如此,这意味着列表已被复制。
如何查看对象是否已被复制?
【问题讨论】:
-
一旦对象被创建,任何东西都不能改变它的ID。
-
@RossRidge:当我复制一个对象时,它不应该在内存中与原始对象不同的位置吗?有没有办法获取这个内存地址(如果
id返回别的东西)? -
谢谢,@JonathanEunice。我试图纠正我的说法。现在还好吗?
-
你没有复制
l所指的对象,你只是修改了它。 -
@RossRidge:我并没有真正修改列表。否则,原始列表(输出的最后一行)将被更改(或者我错过了什么?)。我认为写时复制意味着当我更改对象时会进行复制。有错吗?
标签: python multiprocessing fork shared-memory