copy 

Python 的赋值语句不复制对象,而是创建目标和对象的绑定关系。对于自身可变,或包含可变项的集合,有时要生成副本用于改变操作,而不必改变原始对象。
浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是在Python中用于复制数据结构(如列表)时经常用到的概念。

浅拷贝(Shallow Copy)

浅复制创建了一个新的列表对象,但它不创建列表中的元素的副本。这意味着,如果原列表包含对其他对象的引用(例如,其他列表),新列表和原列表将引用同一个对象(即,它们是容器的副本,但不复制容器中的内容)。
可以通过多种方式进行浅复制,包括使用列表的copy()方法、切片操作符[:]、或者list()构造函数。

直接赋值

original_list = [1, 2, [3, 4]]
shallow_copied_list = original_list

print(original_list == shallow_copied_list)  # 输出 True

# 修改浅拷贝后的列表
shallow_copied_list[0] = 5
shallow_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [6, 4]]
print(shallow_copied_list)  # 输出 [5, 2, [6, 4]]

使用切片(Slice)

这是创建列表的浅拷贝的简单方法。通过使用切片操作来创建一个新的列表,可以得到原始列表的一个副本。由于切片操作会返回一个新的列表对象,因此对新列表的修改不会影响原始列表。
original_list = [1, 2, [3, 4]]
shallow_copied_list = original_list[:]

print(original_list == shallow_copied_list)  # 输出 True

# 修改浅拷贝后的列表
shallow_copied_list[0] = 5
shallow_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [6, 4]]
print(shallow_copied_list)  # 输出 [5, 2, [6, 4]]

使用列表构造函数

可以使用列表的构造函数list()来复制列表,传入原始列表作为参数。这会创建一个新的列表对象,其中包含原始列表的所有元素。
original_list = [1, 2, [3, 4]]
shallow_copied_list = list(original_list)

print(original_list == shallow_copied_list)  # 输出 True

# 修改浅拷贝后的列表
shallow_copied_list[0] = 5
shallow_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [6, 4]]
print(shallow_copied_list)  # 输出 [5, 2, [6, 4]]

使用copy()方法 

列表对象具有一个内置的copy()方法,可以用来创建原始列表的副本。这也是一种创建浅拷贝的方法。
original_list = [1, 2, [3, 4]]
shallow_copied_list = original_list.copy()

print(original_list == shallow_copied_list)  # 输出 True

# 修改浅拷贝后的列表
shallow_copied_list[0] = 5
shallow_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [6, 4]]
print(shallow_copied_list)  # 输出 [5, 2, [6, 4]]

使用 copy 模块

Python的copy模块提供了一个copy()函数,可以用来执行浅复制(shallow copy)。这个函数可以复制一个对象,包括列表对象,但不会复制对象的子对象。对于列表而言,这意味着创建了一个新列表,但列表中的元素仍然是原始列表中元素的引用。
import copy

original_list = [1, 2, [3, 4]]
shallow_copied_list = copy.copy(original_list)

print(original_list == shallow_copied_list)  # 输出 True

# 修改浅复制后的列表
shallow_copied_list[0] = 5
shallow_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [6, 4]]
print(shallow_copied_list)  # 输出 [5, 2, [6, 4]]

深拷贝(Deep Copy)

深复制创建了一个新的列表对象,同时递归地复制列表中的所有对象。这意味着,不仅列表本身被复制,列表中的所有元素(以及元素中的元素,等等)也都被复制。这样,原列表和新列表完全独立,修改一个不会影响到另一个。
进行深复制需要使用copy模块中的deepcopy()函数。

使用deepcopy()进行深拷贝

import copy

original_list = [1, 2, [3, 4]]
deep_copied_list = copy.deepcopy(original_list)

print(original_list == deep_copied_list)  # 输出 True

# 修改深复制后的列表
deep_copied_list[0] = 5
deep_copied_list[2][0] = 6

print(original_list)  # 输出 [1, 2, [3, 4]]
print(deep_copied_list)  # 输出 [5, 2, [6, 4]]

浅复制和深复制的选择

浅拷贝足以用于包含不可变对象(如整数、字符串、元组)的列表,或者当你不需要独立复制内部对象时。
深拷贝通常用于列表包含其他可变对象(如列表、字典或自定义对象)时,你需要完全独立的副本,不希望原始数据和复制数据之间有任何关联。

参考文档

https://docs.python.org/zh-cn/3.12/library/copy.html