1.浅拷贝(Shallow Copy)
在Python中,使用=赋值符号进行拷贝操作,和使用copy()方法进行拷贝操作,得到的均为浅拷贝。
1.1 定义
浅拷贝只复制了原始对象中所包含的元素的引用,而没有复制元素本身,因此,如果修改复制之后的新对象,会影响到原始对象。
1.2 示例
# 定义原始对象
original_list = [[1, 2], [3, 4]]
# 浅拷贝操作
new_list = original_list.copy()
# 修改新对象中的元素
new_list[0][0] = 5
# 打印输出
print('原始对象:', original_list) # 输出:[[5, 2], [3, 4]]
print('浅拷贝的新对象:', new_list) # 输出:[[5, 2], [3, 4]]
通过上述示例,我们可以看到,对新对象中的元素进行修改后,原始对象也受到了影响。
1.3 注意事项
浅拷贝只复制值类型对象本身,而不会复制对象中包含的引用类型对象。
例如:
# 定义包含引用类型对象的原始对象
original_dict = {'key': [1, 2, 3]}
# 浅拷贝操作
new_dict = original_dict.copy()
# 修改新对象中包含的引用类型对象
new_dict['key'][0] = 5
# 打印输出
print('原始对象:', original_dict) # 输出:{'key': [5, 2, 3]}
print('浅拷贝的新对象:', new_dict) # 输出:{'key': [5, 2, 3]}
通过上述示例,我们可以看到,对新对象中包含的引用类型对象进行修改后,原始对象也受到了影响。
2.深拷贝(Deep Copy)
深拷贝则是在复制对象时,将对象及其所有引用类型对象都进行复制,复制后的对象和原始对象互不影响。
2.1 定义
深拷贝会递归复制所有引用类型对象,直到所有的引用类型对象都是值类型对象为止,因此,如果修改复制之后的新对象,不会影响到原始对象。
2.2 示例
# 导入copy模块
import copy
# 定义原始对象
original_dict = {'key': [1, 2, 3]}
# 深拷贝操作
new_dict = copy.deepcopy(original_dict)
# 修改新对象中包含的引用类型对象
new_dict['key'][0] = 5
# 打印输出
print('原始对象:', original_dict) # 输出:{'key': [1, 2, 3]}
print('深拷贝的新对象:', new_dict) # 输出:{'key': [5, 2, 3]}
通过上述示例,我们可以看到,对新对象中包含的引用类型对象进行修改后,原始对象并没有受到影响。
2.3 注意事项
深拷贝会创建一个全新的对象,因此执行深拷贝操作可能会比较耗时。
还有一些特殊情况,例如循环引用的情况,深拷贝操作就会抛出异常。
例如:
# 循环引用的情况
x = [1, 2]
x.append(x)
# 深拷贝操作,会抛出异常
copy.deepcopy(x)
针对这种情况,我们可以使用自定义递归深拷贝方式解决。
def deepcopy(obj):
"""递归实现深拷贝"""
# 如果是值类型对象,则直接拷贝
if not isinstance(obj, (dict, list)):
return obj
# 如果是引用类型对象,则递归拷贝
new_obj = dict() if isinstance(obj, dict) else list()
for key, value in obj.items() if isinstance(obj, dict) else enumerate(obj):
new_obj[key] = deepcopy(value)
return new_obj
# 循环引用的情况
x = [1, 2]
x.append(x)
# 自定义递归深拷贝操作
y = deepcopy(x)
# 打印输出结果
print(x, y)
通过自定义递归深拷贝方式,我们可以避免因循环引用导致深拷贝操作失败。
3.总结
在Python中,浅拷贝和深拷贝的区别在于:浅拷贝只复制元素的引用,而深拷贝会递归复制所有引用类型对象。选择拷贝方式需要根据具体业务场景决定。
对于性能要求比较严格的场景,可以使用浅拷贝方式。而对于需要快速创建全新对象并修改它们的场景,建议使用深拷贝。