Python Copy – 执行深拷贝和浅拷贝

在本文中,我们将了解如何使用 Python Copy模块来执行深复制和浅复制操作。

现在,深复制和浅复制是什么意思?

让我们通过示例来看一下!


为什么我们需要 Python Copy 模块?

在Python中,一切都用对象来表示。因此,很多情况下,我们可能需要直接复制对象。

在这些情况下,我们不能直接使用赋值运算符。

赋值背后的要点是多个变量可以指向同一个对象。这意味着如果对象使用任何这些变量进行更改,更改将反映在各处!

以下示例使用可变的共享列表对象说明了此问题。

a = [1, 2, 3, 4]
 
b = a
 
print(a)
print(b)
 
b.append(5)
 
# Changes will be reflected in a too!
print(a)
print(b)

输出

[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]

正如您所看到的,由于两个变量都指向同一个对象,因此当b发生变化时, 也会发生变化a

为了解决这个问题,Python 给我们提供了一种使用Copy模块的方法。

Python复制模块是标准库的一部分,可以使用以下语句导入:

import copy

现在,在这个模块中,我们主要可以执行两类操作:

  • 浅拷贝
  • 深拷贝

现在让我们来看看这些方法。


浅拷贝

该方法用于执行浅复制操作。

调用该方法的语法为:

import copy
 
new_obj = copy.copy(old_obj) # Perform a shallow copy

这会做两件事——

  • 创建一个新对象
  • 插入在原始对象中找到的对象的所有引用

现在,由于它创建了一个新对象,因此我们可以确定新对象与旧对象不同。

但是,这仍然会保留对嵌套对象的引用。因此,如果我们需要复制的对象有其他可变对象(列表、集合等),这仍然会维护对同一嵌套对象的引用!

为了理解这一点,让我们举个例子。

为了说明第一点,我们将使用一个简单的整数列表来尝试(没有嵌套对象!)

import copy
 
old_list = [1, 2, 3]
 
print(old_list)
 
new_list = copy.copy(old_list)
 
# Let's try changing new_list
new_list.append(4)
 
# Changes will not be reflected in the original list, since the objects are different
print(old_list)
print(new_list)

输出

[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3]

正如你所看到的,如果我们的对象是一个简单的列表,那么浅复制没有问题。

让我们看另一种情况,我们的对象是列表的列表。

import copy
 
old_list = [[1, 2], [1, 2, 3]]
 
print(old_list)
 
new_list = copy.copy(old_list)
 
# Let's try changing a nested object inside the list
new_list[1].append(4)
 
# Changes will be reflected in the original list, since the object contains a nested object
print(old_list)
print(new_list)

输出

[[1, 2], [1, 2, 3]]
[[1, 2], [1, 2, 3, 4]]
[[1, 2], [1, 2, 3, 4]]

在这里,请注意 和 都old_list受到new_list了影响!

如果必须避免这种行为,则必须递归复制所有对象以及嵌套对象。

这称为使用 Python 复制模块的深度复制操作。


深拷贝

此方法类似于浅复制方法,但现在将原始对象(包括嵌套对象)中的所有内容复制到新对象中。

要进行深复制操作,我们可以使用以下语法:

import copy
 
new_object = copy.deepcopy(old_object)

让我们以旧的例子为例,尝试使用深层复制来解决我们的问题。

import copy
 
old_list = [[1, 2], [1, 2, 3]]
 
print(old_list)
 
new_list = copy.deepcopy(old_list)
 
# Let's try changing a nested object inside the list
new_list[1].append(4)
 
# Changes will be reflected in the original list, since the objects are different
print(old_list)
print(new_list)

输出

[[1, 2], [1, 2, 3]]
[[1, 2], [1, 2, 3]]
[[1, 2], [1, 2, 3, 4]]

请注意,旧列表没有变化。由于所有对象都是递归复制的,所以现在没有问题了!

然而,由于复制所有对象,与浅复制方法相比,这种深复制方法的成本要高一些。

因此,仅在需要时明智地使用它!


结论

在本文中,我们学习了如何使用 Python Copy 模块来执行浅复制和深复制操作。

参考

  • Python 复制模块文档
  • JournalDev 关于 Python 复制模块的文章