python list.copy shallow vs deep copy
python list.copy shallow vs deep copy
也许我对浅拷贝的定义理解有误...但我非常困惑:
根据文档:
其中"s"是一个列表(同样的问题也适用于字典)。
"s.copy() | 创建s的浅拷贝(等同于s[:])"
但我认为s[:]是深拷贝。例如,参考如何复制列表的这个stackoverflow答案(避免只是指向原始版本)。而且使用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]
看起来l1、l2和l3是三个独立的对象。我错过了什么吗?
深拷贝和浅拷贝是Python中列表拷贝的两种方式。浅拷贝只会复制列表的顶层元素,如果顶层元素中有其他列表,拷贝的结果仍然会引用原始列表。这就是使用l1[:]
和l1.copy()
实现的浅拷贝。
而深拷贝会递归地复制所有层级的元素,包括列表中的列表。拷贝的结果中不会存在引用关系。这就是copy.deepcopy()
实现的深拷贝。
浅拷贝的原因是为了节省内存空间,当我们只需要拷贝列表的顶层元素时,使用浅拷贝可以减少内存的占用。然而,如果我们希望完全独立地拷贝列表及其所有层级的元素,就需要使用深拷贝。
下面是一个示例代码,展示了浅拷贝和深拷贝的区别:
import copy l1 = [1, 2, [3, 4]] l2 = l1[:] # 浅拷贝 l3 = l1.copy() # 浅拷贝 l4 = copy.deepcopy(l1) # 深拷贝 l2[0] = 5 l2[2][0] = 6 print(l1) # 输出: [1, 2, [6, 4]] print(l2) # 输出: [5, 2, [6, 4]] print(l3) # 输出: [1, 2, [6, 4]] print(l4) # 输出: [1, 2, [3, 4]]
从上面的示例中可以看出,浅拷贝的结果中,列表中的列表仍然是引用关系,所以修改了l2的元素也会影响到l1和l3。而深拷贝的结果中没有引用关系,所以l4不会受到l1和l2的影响。
解决这个问题的方法就是根据需求选择使用浅拷贝还是深拷贝。如果只需要拷贝列表的顶层元素,可以使用浅拷贝;如果需要完全独立地拷贝列表及其所有层级的元素,就需要使用深拷贝。
深浅拷贝是在Python中处理列表复制时经常遇到的问题。浅拷贝意味着新的列表持有与旧列表相同的对象的引用。这意味着对新列表中的对象进行的更改也会“污染”旧列表。然而,深拷贝则创建一个新的列表的副本,而不仅仅是复制对旧列表的引用。
例如,考虑以下代码片段:
foo = [1, 2, []] bar = foo.copy() bar[-1].append(3) print(foo)
输出结果为:[1, 2, [3]],这是因为对`bar`中的列表进行的更改也影响了`foo`。
另一方面,如果使用深拷贝,代码如下:
import copy foo = [1, 2, []] bar = copy.deepcopy(foo) bar[-1].append(3) print(foo)
输出结果为:[1, 2, []],这是因为深拷贝创建了一个新的列表的副本,而不仅仅是复制对旧列表的引用。
为了解决这个问题,我们可以使用深拷贝来确保在复制列表时不会影响原始列表。使用`copy`模块的`deepcopy`函数可以实现深拷贝。这样,通过创建一个新的对象副本,我们可以确保对新列表的更改不会影响原始列表。