【问题标题】:python list.copy shallow vs deep copy [duplicate]python list.copy浅拷贝与深拷贝[重复]
【发布时间】:2017-10-14 11:58:54
【问题描述】:

也许我不明白浅拷贝的定义……但我很困惑:

来自文档:

其中“s”是一个列表(但同样的问题分别适用于字典)。

"s.copy() | 创建 s 的浅拷贝(与 s[:] 相同)"

除了我认为s[:] 是一个深拷贝。例如,请参阅this stack overflow answer 了解如何复制列表(不只是指向原始版本)。并且使用 list1.copy() 似乎可以进行深层复制,也就是与 [:]

相同的行为
l1 = [1,2,3,4]
l2 = l1[:]
l3 = l1.copy()



l2.append(5)
l3[0] = 99
print(l1)
print(l2)
print(l3)
>> [1,2,3,4]
>> [1,2,3,4,5]
>> [99,2,3,4]

看起来l1l2l3 都是单独的 对象。我错过了什么?

【问题讨论】:

  • ...如果我将 l1 更改为数字列表列表,我仍然会得到相同的结果 - l1.copy() 似乎创建了一个单独的对象
  • 没有。这些都是浅拷贝。该问题的区别在于单纯的分配(根本不复制)和复制(浅的)
  • @juanpa.arrivillaga, Ahhhh 好的,我明白了。
  • @RSHAP 你可以用is 测试深度相等,用== 测试浅相等。在这里,深层平等意味着浅层平等。 (l1 is l2 仅是 True,如果两个引用都指向同一个对象,而 l1 == l2True,当 l1l2 的所有值都相等时)

标签: python list deep-copy shallow-copy


【解决方案1】:

您只是误解了在这种情况下“浅”和“深”的含义。

浅拷贝只是顶层元素的拷贝。如果这些元素中的任何一个本身就是列表,则副本仍将引用原始列表。 l1[:]l1.copy() 都是这样做的。

深拷贝是所有级别的拷贝。如果任何元素是列表,它们也将被深度复制。不会共享任何参考。这就是copy.deepcopy() 所做的。

【讨论】:

    【解决方案2】:

    浅拷贝意味着新列表包含对与旧列表相同的对象的引用。

    例如:

    foo = [1, 2, []]
    bar = foo.copy()
    bar[-1].append(3)
    print(foo)
    

    我们将看到bar 中对象的突变也会“污染”foo

    如果我们使用深拷贝重做这个例子,情况就不同了:

    import copy
    foo = [1, 2, []]
    bar = copy.deepcopy(foo)
    bar[-1].append(3)
    print(foo)
    

    这是因为深拷贝会创建列表的新(深拷贝),而不是仅仅复制对旧列表的引用。

    【讨论】: