python list.copy shallow vs deep copy

5 浏览
0 Comments

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是三个独立的对象。我错过了什么吗?

0
0 Comments

深拷贝和浅拷贝是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的影响。

解决这个问题的方法就是根据需求选择使用浅拷贝还是深拷贝。如果只需要拷贝列表的顶层元素,可以使用浅拷贝;如果需要完全独立地拷贝列表及其所有层级的元素,就需要使用深拷贝。

0
0 Comments

深浅拷贝是在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`函数可以实现深拷贝。这样,通过创建一个新的对象副本,我们可以确保对新列表的更改不会影响原始列表。

0