python中的深浅拷贝
浅拷贝 (Shallow Copy)
浅拷贝创建一个新对象,但只复制原对象的引用,而不复制引用的对象本身。
实现方式
import copy
# 原始列表
original_list = [1, 2, 3]
# 方法1: 使用copy模块的copy()函数
shallow_copied1 = copy.copy(original_list)
# 方法2: 对于列表,可以使用切片操作
shallow_copied2 = original_list[:]
# 方法3: 使用list()构造函数
shallow_copied3 = list(original_list)
# 方法4: 使用对象的copy()方法(如果可用)
shallow_copied4 = original_list.copy()
浅拷贝的特点
import copy
# 示例1: 简单列表(无嵌套)
original = [1, 2, 3]
copied = copy.copy(original)
print("修改前:")
print(f"original: {original}") # [1, 2, 3]
print(f"copied: {copied}") # [1, 2, 3]
# 修改原始列表的第一层元素
original[0] = 100
print("\n修改后:")
print(f"original: {original}") # [100, 2, 3]
print(f"copied: {copied}") # [1, 2, 3] - 不受影响
修改前:
original: [1, 2, 3]
copied: [1, 2, 3]
修改后:
original: [100, 2, 3]
copied: [1, 2, 3]
# 示例2: 嵌套列表(展示浅拷贝的局限性)
import copy
original = [1, 2, [3, 4]]
copied = copy.copy(original)
print("修改前:")
print(f"original: {original}") # [1, 2, [3, 4]]
print(f"copied: {copied}") # [1, 2, [3, 4]]
print(f"\n嵌套列表的ID:")
print(f"original[2] id: {id(original[2])}") # 某个内存地址
print(f"copied[2] id: {id(copied[2])}") # 相同的地址!
# 修改原始数据的嵌套部分
original[2][0] = 300
print("\n修改嵌套元素后:")
print(f"original: {original}") # [1, 2, [300, 4]]
print(f"copied: {copied}") # [1, 2, [300, 4]] - 也被修改了!
修改前:
original: [1, 2, [3, 4]]
deep_copied: [1, 2, [3, 4]]
嵌套列表的ID:
original[2] id: 1994301925120
deep_copied[2] id: 1994301925376
修改嵌套元素后:
original: [1, 2, [300, 4]]
deep_copied: [1, 2, [3, 4]]
深拷贝 (Deep Copy)
深拷贝创建一个新对象,并递归地复制原对象及其所有子对象。
实现方式
import copy
original_list = [1, 2, [3, 4]]
deep_copied = copy.deepcopy(original_list)
深拷贝的特点
import copy
# 示例
original = [1, 2, [3, 4]]
deep_copied = copy.deepcopy(original)
print("修改前:")
print(f"original: {original}") # [1, 2, [3, 4]]
print(f"deep_copied: {deep_copied}") # [1, 2, [3, 4]]
print(f"\n嵌套列表的ID:")
print(f"original[2] id: {id(original[2])}") # 某个内存地址
print(f"deep_copied[2] id: {id(deep_copied[2])}") # 不同的地址!
# 修改原始数据的嵌套部分
original[2][0] = 300
print("\n修改嵌套元素后:")
print(f"original: {original}") # [1, 2, [300, 4]]
print(f"deep_copied: {deep_copied}") # [1, 2, [3, 4]] - 完全不受影响
修改前:
original: [1, 2, [3, 4]]
deep_copied: [1, 2, [3, 4]]
嵌套列表的ID:
original[2] id: 1994301936192
deep_copied[2] id: 1994301932352
修改嵌套元素后:
original: [1, 2, [300, 4]]
deep_copied: [1, 2, [3, 4]]
综合对比示例
import copy
# 创建包含多层嵌套结构的原始数据
original = [1, 2, ['a', 'b', {'x': 1, 'y': 2}]]
# 浅拷贝
shallow_copy = copy.copy(original)
# 深拷贝
deep_copy = copy.deepcopy(original)
print("=== 内存地址对比 ===")
print(f"原始列表ID: {id(original)}")
print(f"浅拷贝列表ID: {id(shallow_copy)}")
print(f"深拷贝列表ID: {id(deep_copy)}")
print(f"\n原始嵌套列表ID: {id(original[2])}")
print(f"浅拷贝嵌套列表ID: {id(shallow_copy[2])}") # 与原始相同
print(f"深拷贝嵌套列表ID: {id(deep_copy[2])}") # 新的ID
print(f"\n原始嵌套字典ID: {id(original[2][2])}")
print(f"浅拷贝嵌套字典ID: {id(shallow_copy[2][2])}") # 与原始相同
print(f"深拷贝嵌套字典ID: {id(deep_copy[2][2])}") # 新的ID
# 修改测试
print("\n=== 修改测试 ===")
original[2][0] = 'MODIFIED'
original[2][2]['x'] = 999
print(f"原始: {original}") # [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
print(f"浅拷贝: {shallow_copy}") # [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]] - 受影响
print(f"深拷贝: {deep_copy}") # [1, 2, ['a', 'b', {'x': 1, 'y': 2}]] - 不受影响
=== 内存地址对比 ===
原始列表ID: 1994285283008
浅拷贝列表ID: 1994285284800
深拷贝列表ID: 1994301925120
原始嵌套列表ID: 1994285283712
浅拷贝嵌套列表ID: 1994285283712
深拷贝嵌套列表ID: 1994301923968
原始嵌套字典ID: 1994285271808
浅拷贝嵌套字典ID: 1994285271808
深拷贝嵌套字典ID: 1994285276224
=== 修改测试 ===
原始: [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
浅拷贝: [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
深拷贝: [1, 2, ['a', 'b', {'x': 1, 'y': 2}]]
字典的拷贝示例
import copy
# 字典的拷贝
original_dict = {
'name': 'Alice',
'scores': [85, 92, 78],
'info': {'age': 25, 'city': 'Beijing'}
}
# 浅拷贝
shallow_dict = copy.copy(original_dict)
# 深拷贝
deep_dict = copy.deepcopy(original_dict)
# 修改测试
original_dict['scores'][0] = 100
original_dict['info']['age'] = 26
print("原始字典:", original_dict)
# {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
print("浅拷贝字典:", shallow_dict)
# {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
print("深拷贝字典:", deep_dict)
# {'name': 'Alice', 'scores': [85, 92, 78], 'info': {'age': 25, 'city': 'Beijing'}}
原始字典: {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
浅拷贝字典: {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
深拷贝字典: {'name': 'Alice', 'scores': [85, 92, 78], 'info': {'age': 25, 'city': 'Beijing'}}
实际应用场景
浅拷贝适用场景
# 场景1: 数据结构简单,没有嵌套的可变对象
config = {'debug': True, 'port': 8080}
backup_config = config.copy() # 或 copy.copy(config)
# 场景2: 需要共享某些数据
shared_data = {'last_updated': '2024-01-01'}
cache1 = {'data': shared_data}
cache2 = cache1.copy()
# cache1和cache2共享同一个last_updated字典
深拷贝适用场景
# 场景1: 需要完全独立的配置模板
template = {
'database': {
'host': 'localhost',
'port': 5432,
'credentials': {'user': 'admin', 'password': 'secret'}
},
'settings': {'timeout': 30, 'retries': [1, 2, 3]}
}
# 为不同环境创建独立配置
development_config = copy.deepcopy(template)
production_config = copy.deepcopy(template)
# 修改开发配置不会影响生产配置
development_config['database']['host'] = 'dev-server'
development_config['settings']['retries'][0] = 0
性能考虑
import copy
import time
# 创建大型嵌套数据结构
def create_large_data():
return [[[i*j*k for k in range(100)] for j in range(100)] for i in range(10)]
large_data = create_large_data()
# 测试浅拷贝性能
start = time.time()
shallow_copy = copy.copy(large_data)
shallow_time = time.time() - start
# 测试深拷贝性能
start = time.time()
deep_copy = copy.deepcopy(large_data)
deep_time = time.time() - start
print(f"浅拷贝时间: {shallow_time:.6f}秒")
print(f"深拷贝时间: {deep_time:.6f}秒")
print(f"深拷贝比浅拷贝慢 {deep_time/shallow_time:.2f} 倍")
总结表格
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制层级 | 只复制第一层 | 递归复制所有层级 |
| 嵌套对象 | 共享引用 | 创建新对象 |
| 内存使用 | 较少 | 较多 |
| 性能 | 较快 | 较慢 |
| 修改影响 | 嵌套对象修改会影响拷贝 | 完全独立,互不影响 |
| 适用场景 | 简单结构或需要共享嵌套对象时 | 需要完全独立副本时 |
关键要点
- 浅拷贝:创建新容器,但填充的是对原对象内容的引用
- 深拷贝:创建新容器,并递归地添加原对象内容的副本
- 对于不可变对象(数字、字符串、元组等),深浅拷贝没有区别
- 当不确定时,使用深拷贝可以避免意外的副作用
- 考虑性能,对于大型数据结构,深拷贝可能较慢

浙公网安备 33010602011771号