本文目录导读:

在Python中,深度拷贝(deep copy)可以通过 copy 模块的 deepcopy() 函数来实现,深度拷贝会创建一个全新的对象,并递归地复制所有嵌套的对象,使得原对象和拷贝对象完全独立。
基本实现
使用 copy.deepcopy()
import copy
# 示例对象
original = {
'name': 'Alice',
'hobbies': ['reading', 'swimming'],
'address': {
'city': 'Beijing',
'zip': '100000'
}
}
# 深度拷贝
copied = copy.deepcopy(original)
# 修改拷贝对象
copied['hobbies'].append('coding')
copied['address']['city'] = 'Shanghai'
print("Original:", original)
print("Copied:", copied)
自定义深度拷贝实现
如果你想理解深度拷贝的原理,可以自己实现一个简单的版本:
def deep_copy(obj):
"""自定义深度拷贝函数"""
# 处理基本类型(不可变类型)
if obj is None:
return None
if isinstance(obj, (int, float, bool, str, bytes)):
return obj
# 处理列表
if isinstance(obj, list):
return [deep_copy(item) for item in obj]
# 处理字典
if isinstance(obj, dict):
return {key: deep_copy(value) for key, value in obj.items()}
# 处理元组
if isinstance(obj, tuple):
return tuple(deep_copy(item) for item in obj)
# 处理集合
if isinstance(obj, set):
return {deep_copy(item) for item in obj}
# 处理其他对象
try:
# 尝试创建新的对象实例
new_obj = obj.__class__.__new__(obj.__class__)
if hasattr(obj, '__dict__'):
for key, value in obj.__dict__.items():
setattr(new_obj, key, deep_copy(value))
return new_obj
except Exception as e:
# 如果无法处理,返回原对象
print(f"Warning: Could not deep copy {type(obj)}: {e}")
return obj
# 测试自定义深度拷贝
class Person:
def __init__(self, name, age, hobbies):
self.name = name
self.age = age
self.hobbies = hobbies
def __repr__(self):
return f"Person(name='{self.name}', age={self.age}, hobbies={self.hobbies})"
# 创建测试对象
original_person = Person("Bob", 30, ["reading", "swimming"])
copied_person = deep_copy(original_person)
# 修改拷贝对象
copied_person.hobbies.append("coding")
print("Original:", original_person)
print("Copied:", copied_person)
实际应用案例
import copy
class ShoppingCart:
"""购物车示例"""
def __init__(self):
self.items = []
self.discounts = []
def add_item(self, item, price, quantity=1):
self.items.append({
'item': item,
'price': price,
'quantity': quantity
})
def add_discount(self, code, percentage):
self.discounts.append({
'code': code,
'percentage': percentage
})
def __repr__(self):
return f"Items: {self.items}\nDiscounts: {self.discounts}"
# 创建原始购物车
cart1 = ShoppingCart()
cart1.add_item("Apple", 5.0, 3)
cart1.add_item("Banana", 3.0, 2)
cart1.add_discount("SUMMER20", 20)
# 深度拷贝购物车
cart2 = copy.deepcopy(cart1)
# 修改 cart2
cart2.add_item("Orange", 4.0, 1)
cart2.add_discount("WINTER10", 10)
cart2.items[0]['quantity'] = 5
print("Cart 1 (Original):")
print(cart1)
print("\nCart 2 (Copied and modified):")
print(cart2)
# 验证完全独立
print("\nAre cart1 and cart2 independent?")
print(f"cart1 is cart2: {cart1 is cart2}") # False
print(f"cart1.items is cart2.items: {cart1.items is cart2.items}") # False
处理循环引用
深度拷贝还能正确处理循环引用的情况:
import copy
class Node:
def __init__(self, value):
self.value = value
self.next = None
self.prev = None
def __repr__(self):
return f"Node({self.value})"
# 创建循环链表
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node1.next = node2
node2.prev = node1
node2.next = node3
node3.prev = node2
node3.next = node1 # 形成循环引用
node1.prev = node3
# 深度拷贝循环引用的对象
copied_node1 = copy.deepcopy(node1)
print("Original node1:", id(node1))
print("Copied node1:", id(copied_node1))
print("Are they the same object?", node1 is copied_node1) # False
print("Original circular reference preserved:", copied_node1.next.next.next.value) # 1
性能考虑
对于大数据量,深度拷贝可能比较耗时:
import copy
import time
# 创建一个包含大量数据的列表
big_data = [[i for i in range(1000)] for _ in range(1000)]
# 比较浅拷贝和深拷贝的性能
start = time.time()
shallow = copy.copy(big_data)
shallow_time = time.time() - start
start = time.time()
deep = copy.deepcopy(big_data)
deep_time = time.time() - start
print(f"Shallow copy time: {shallow_time:.4f} seconds")
print(f"Deep copy time: {deep_time:.4f} seconds")
# 修改测试
shallow[0][0] = -1
print(f"Modifying shallow copy affects original: {big_data[0][0] == -1}") # True
deep[0][0] = -2
print(f"Modifying deep copy affects original: {big_data[0][0] == -2}") # False
注意事项
- 不可变类型:字符串、数字等不可变类型在深拷贝时不会真正创建新对象
- 自定义对象:确保自定义类正确地实现了
__deepcopy__方法 - 性能问题:深度拷贝大型对象或复杂嵌套结构时要注意性能
- 内存占用:深度拷贝会创建完全独立的对象,占用更多内存
- 文件/网络连接:不能深度拷贝文件句柄、网络连接等系统资源
深度拷贝是Python中处理复杂对象复制的重要工具,特别是在需要完全独立的副本时非常有用。