Python 的深拷贝与浅拷贝详解
在 Python 中,拷贝(copy)是指创建一个对象的副本。根据复制的深度,Python 提供了两种类型的拷贝:浅拷贝(shallow copy)和深拷贝(deep copy)。理解它们之间的区别对于避免程序中的潜在错误至关重要,尤其是在涉及到可变对象(如列表、字典、集合等)时。
1. 浅拷贝(Shallow Copy)
浅拷贝是指创建一个新的对象,但是对于原对象中包含的引用类型(如列表中的其他列表),不会创建新的副本,而是直接引用原对象中的内容。简而言之,浅 拷贝仅复制对象本身,并没有递归地复制对象内部的元素。
浅拷贝的工作原理
如何进行浅拷贝?
可以使用以下几种方法来创建浅拷贝:
copy.copy()
:标准库中提供的浅拷贝函数。dict.copy()
:对于字典,可以直接调用 copy()
方法。示例:
import copy
# 浅拷贝:使用 copy.copy() 创建副本
original_list = [1, 2, [3, 4]]
shallow_copy = copy.copy(original_list)
print(original_list) # 输出: [1, 2, [3, 4]]
print(shallow_copy) # 输出: [1, 2, [3, 4]]
# 修改浅拷贝中的嵌套列表
shallow_copy[2][0] = 99
print(original_list) # 输出: [1, 2, [99, 4]],原对象中的嵌套列表也发生了变化
print(shallow_copy) # 输出: [1, 2, [99, 4]],副本中的嵌套列表也发生了变化
在上面的例子中,original_list
和 shallow_copy
拥有相同的嵌套列表 [3, 4]
,修改嵌套列表的内容时,原对象和浅拷贝都会受影响。这是因为浅拷贝仅复制了外部列表,内部的嵌套列表仍然指向相同的内存位置。
浅拷贝的限制
2. 深拷贝(Deep Copy)
深拷贝是指创建一个新的对象,并且递归地复制原对象中的所有元素及其内部的可变对象。换句话说,深拷贝不仅复制对象本身,还复制对象内部的所有元素,直到所有嵌套对象都被完全复制为止。
深拷贝的工作原理
如何进行深拷贝?
copy.deepcopy()
:标准库中提供的深拷贝函数。示例:
import copy
# 深拷贝:使用 copy.deepcopy() 创建副本
original_list = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(original_list)
print(original_list) # 输出: [1, 2, [3, 4]]
print(deep_copy) # 输出: [1, 2, [3, 4]]
# 修改深拷贝中的嵌套列表
deep_copy[2][0] = 99
print(original_list) # 输出: [1, 2, [3, 4]],原对象没有改变
print(deep_copy) # 输出: [1, 2, [99, 4]],副本中的嵌套列表已改变
在这个例子中,original_list
和 deep_copy
是完全独立的,即使修改了 deep_copy
中的嵌套列表,original_list
不会受到任何影响。
深拷贝的特点
3. 浅拷贝与深拷贝的区别
特性 | 浅拷贝(Shallow Copy) | 深拷贝(Deep Copy) |
---|---|---|
复制对象 | 仅复制最外层对象 | 复制最外层对象及所有嵌套对象 |
嵌套对象是否复制 | 嵌套对象仍然引用原对象中的元素 | 嵌套对象会被完全复制 |
内部对象的修改是否影响原对象 | 修改内部对象会影响原对象和副本 | 修改副本的嵌套对象不会影响原对象 |
创建副本的时间 | 速度较快,拷贝过程较简单 | 速度较慢,需要递归遍历每一层嵌套对象 |
示例:
import copy
# 浅拷贝
original = {'a': 1, 'b': [1, 2, 3]}
shallow = copy.copy(original)
shallow['b'][0] = 99
print(original) # 输出: {'a': 1, 'b': [99, 2, 3]}
print(shallow) # 输出: {'a': 1, 'b': [99, 2, 3]},修改共享的列表
# 深拷贝
deep = copy.deepcopy(original)
deep['b'][1] = 100
print(original) # 输出: {'a': 1, 'b': [99, 2, 3]}
print(deep) # 输出: {'a': 1, 'b': [99, 100, 3]},修改副本不会影响原对象
4. 什么时候使用浅拷贝和深拷贝
5. 总结
理解浅拷贝和深拷贝的差异,有助于避免因共享可变对象而导致的错误,特别是在处理复杂数据结构时。
作者:威桑