我有2个名单:
l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = list(l1)
根据this帖子,如果我修改l2
,则l1
不应更改。
但如果我这样做:
del l2[1][1]
l1
也将被修改。
这是否有意,我该如何防止它发生?
我还注意到l1[1]
和l2[1]
的ID是相同的。
答案 0 :(得分:2)
list(l1)
将制作l1
的浅拷贝;也就是说,列表l1
中的所有引用都将被复制到新列表中。由于您使用相同的引用修改对象,因此在原始列表中将显示对这些嵌套列表的修改。
查看列表的匹配id
:
print("l1 object references: ", *map(id, l1))
l1 object references: 139927285488584 139927284661256 139927284723784
print("l2 object references: ", *map(id, l2))
l2 object references: 139927285488584 139927284661256 139927284723784
如果您没有列表中的列表,这不会成为问题:
l1 = [1,2,3]
l2 = list(l1)
del l2[1]
print(l1) # [1, 2, 3]
print(l2) # [1, 3]
解决方案是使用copy.deepcopy
:
list
import copy
l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = copy.deepcopy(l1)
del l2[1][1]
print(l1) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
现在嵌套列表的id
是不同的,而变异的列表只留下另一个:
print("l1 object references: ", *map(id, l1))
l1 object references: 139927284726984 139927284737160 139927284737800
print("l2 object references: ", *map(id, l2))
l2 object references: 139927284710216 139927285123976 139927284678344
当然,在每个元素上调用list
的列表理解也足以实现相同的效果: - )
答案 1 :(得分:1)
这是因为您有一个列表列表。相反,如果你写:
l2 = [list(li) for li in l1]
您可以删除或修改l2
的元素,而无需更改l1
。这是因为,当一个人有一个列表列表时,l2 = list(l1)
会创建一个外部列表的副本,但l2
的内部列表仍然是对l1
的原始内部列表的引用。因此,如果您更改l2
内部列表中的元素,这些更改将反映在l1
的原始内部列表中。如果你创建了l1
内部列表的显式副本,就像我上面所做的那样,你可以避免这个问题。
答案 2 :(得分:-1)
这就是你要找的东西:
l2 = [i[:] for i in l1]
这是有效的,因为您需要按值而不是外部列表实际复制内部列表,以使它们完全独立。
以下是有关其工作原理的示例:
l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = [i[:] for i in l1]
l2[0][0]=3
print (l2) #[[3, 2, 3], [4, 5, 6], [7, 8, 9]]
print (l1) #[[1, 2, 3], [4, 5, 6], [7, 8, 9]]