修改列表的克隆(python)

时间:2016-10-27 11:13:27

标签: python list python-3.x

我有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是相同的。

3 个答案:

答案 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]]