Python 中的浅复制与深复制

在本文中,我们将了解浅复制与深复制之间的区别。我们时不时地需要在程序中创建各种变量的副本/克隆。这可以通过使用浅复制或深复制来完成。

浅复制与深复制

我们将在本教程中研究浅复制和深复制之间的区别。那么让我们开始吧!

浅复制

我们来看下面的一段代码。

1
2
3
4
5
6
7
l1 = [[10,20,30],[40,50,60],[70,80,90]]
l2 = list(l1)
print("list 1: ",l1)
print("list 2: ",l2)
l1.append(['I am new element'])
print("new list 1: ",l1)
print("new list 2: ",l2)

代码的输出看起来像这样。

list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
new list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90], ['I am new element']]
new list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]

现在我们可以在这里看到l2使用l1列表创建的。l2列表是一个新的独立列表,稍后可以看到。当 l1 中添加新元素时,l2 保持不变!

这就是所谓的浅复制!但现在让我们看看下面给出的代码。

1
2
3
4
5
6
7
8
l1 = [[10,20,30],[40,50,60],[70,80,90]]
l2 = list(l1)
print("list 1: ",l1)
print("list 2: ",l2)
 
l1[2][1] = 'I am changed'
print("new list 1: ",l1)
print("new list 2: ",l2)

你认为输出会是什么?在阅读输出之前自己尝试一下!发现什么奇怪的地方了吗?是的!这次l2也改变了。

代码的输出如下所示。

list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
new list 1:  [[10, 20, 30], [40, 50, 60], [70, 'I am changed', 90]]
new list 2:  [[10, 20, 30], [40, 50, 60], [70, 'I am changed', 90]]

这背后的原因是,即使l2是l1的浅拷贝,l1和l2的元素仍然引用相同的内存位置。因此,对一个列表的初始元素进行任何更改也会更改第二个列表。

您还可以使用模块的copy功能创建浅拷贝copy,如下面的代码所示。您可以看到输出看起来完全相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
import copy
l1 = [[10,20,30],[40,50,60],[70,80,90]]
l2 = copy.copy(l1)
print("list 1: ",l1)
print("list 2: ",l2)
print()
l1.append(['new'])
print("new list 1: ",l1)
print("new list 2: ",l2)
print()
l1[2][1] = 'change'
print("new list 1: ",l1)
print("new list 2: ",l2)

代码的输出如下所示。您可以看到输出与之前的方法相同。

list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
 
new list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90], ['new']]
new list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
 
new list 1:  [[10, 20, 30], [40, 50, 60], [70, 'change', 90], ['new']]
new list 2:  [[10, 20, 30], [40, 50, 60], [70, 'change', 90]]

深度复制

现在让我们运行以下代码并查看输出的差异。

1
2
3
4
5
6
7
8
9
import copy
l1 = [[10,20,30],[40,50,60],[70,80,90]]
l2 = copy.deepcopy(l1)
print("list 1: ",l1)
print("list 2: ",l2)
 
l1[2][1] = 'change'
print("new list 1: ",l1)
print("new list 2: ",l2)

这次看到输出感到惊讶吗?通过使用copy模块和deepcopy同一模块的功能,两个列表在各个方面都变得完全独立。

深度复制代码的输出如下所示。

list 1:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
new list 1:  [[10, 20, 30], [40, 50, 60], [70, 'change', 90]]
new list 2:  [[10, 20, 30], [40, 50, 60], [70, 80, 90]]

结论

今天我们学习了Python中的浅拷贝和深拷贝。我们还了解到,浅复制对象只是部分独立于原始对象。而在深度复制中,对象是完全相互独立的。

深复制的缺点之一是比实现浅复制慢。两者都可以使用复制模块来实现。

感谢您的阅读!希望你学到了一些东西!