我需要从许多进程中访问一组大型且不可选的Python对象。因此,我希望确保这些对象不会完全被复制。
根据这篇和这篇文章中的评论,在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都是相同的。即使列表在最后保持不变(正如预期的那样),这也意味着列表已经被复制了。
我该如何查看一个对象是否已被复制?
l
所引用的对象,而是修改了它。 - Ross Ridge