文章目录
- 1. 基本概念
- 1.1 前置知识
- 1.2 浅拷贝(Shallow Copy)
- 1.3 深拷贝(Deep Copy)
- 2. 如何实现浅拷贝和深拷贝
- 3. 深入分析
在 Python 中,数据复制是常见需求。复制机制分为“浅拷贝(shallow copy)”和“深拷贝(deep copy)”,这两种方式在处理复杂数据结构时的行为差异极大。下面详细解析这两种拷贝方法,包括它们的定义、如何使用、适用场景以及它们在内存操作上的不同表现。
1. 基本概念
1.1 前置知识
在 Python 中,所有数据都是以对象的形式表示的,这包括简单的数值、字符串,以及复杂的列表、字典等。
对象可以分为“可变对象”和“不可变对象”。
- 不可变对象(如整数、字符串和元组)不允许对象本身的内容被改变
- 可变对象(如列表、字典)则允许对象内容的修改。
1.2 浅拷贝(Shallow Copy)
浅拷贝仅仅复制数据结构的第一层对象本身,如果对象包含了其他对象的引用,则这些引用的地址不变。也就是说,浅拷贝创建了一个新对象,但是这个新对象中填充的是对原始对象内容的引用(即地址)。
1.3 深拷贝(Deep Copy)
深拷贝对原始数据的完全拷贝,包括数据结构中的所有层级。如果原始对象中含有对其他对象的引用,深拷贝不仅复制结构本身,还会递归地复制所有引用的具体内容,因此新对象与原始对象无任何关联。
2. 如何实现浅拷贝和深拷贝
Python 的 copy 模块提供了实现浅拷贝和深拷贝的方法。
示例代码
以下代码演示了浅拷贝与深拷贝的基本用法:
import copy# 创建一个包含其他对象的复杂对象
original_list = [1, 2, [3, 4], {'a': 5}]# 浅拷贝: 复制顶层对象,内部容器对象如列表和字典保持引用不变
shallow_copied_list = copy.copy(original_list)# 深拷贝: 完全复制所有层级的对象,无引用关系保留
deep_copied_list = copy.deepcopy(original_list)# 修改原始数据中的列表和字典
original_list[2].append(5) # 这会影响浅拷贝中的相应列表
original_list[3]['a'] = 6 # 这也会影响浅拷贝中的相应字典# 输出原始数据和两种拷贝的结果
print("Original:", original_list) # 显示原始对象的当前状态
print("Shallow Copy:", shallow_copied_list) # 显示浅拷贝对象的当前状态
print("Deep Copy:", deep_copied_list) # 显示深拷贝对象的当前状态
运行结果
运行上述代码会得到以下输出:
Original: [1, 2, [3, 4, 5], {'a': 6}]
Shallow Copy: [1, 2, [3, 4, 5], {'a': 6}]
Deep Copy: [1, 2, [3, 4], {'a': 5}]
- 浅拷贝对象的子列表和字典与原始对象一致,因为它们是引用。
- 深拷贝对象的子列表和字典独立于原始对象,对原始对象的修改不影响深拷贝对象。
3. 深入分析
内存效率
浅拷贝由于只复制一层对象,因此在执行速度和所占内存上比深拷贝更为高效。对于大规模数据结构,频繁使用深拷贝可能导致明显的性能下降。
使用场景
- 浅拷贝适用于对象结构简单或只需复制顶层结构的场景。比如当需要复制的对象包含大量不可变数据或共享数据时。
- 深拷贝则适用于需要完全独立副本的复杂数据结构,如多层嵌套的列表或字典。
注意事项
在使用深拷贝时,需要注意递归引用的问题,即对象自身直接或间接地引用了自己。这种情况下,深拷贝会尝试无限复制,最终导致栈溢出错误。
参考:copy in Python (Deep Copy and Shallow Copy)
推荐: python 错误记录