浅拷贝(copy)
- 只复制对象的顶层
- 如果对象内部还有子对象(如列表嵌套列表),子对象不会被复制,新旧对象共享同一个子对象
深拷贝(deepcopy)
- 递归复制对象的所有层级
- 子对象也会被完全复制,新旧对象完全独立,互不影响
代码示例
import copy
# 原对象:嵌套列表
original = [[1, 2, 3], [4, 5, 6]]
# 浅拷贝
shallow = copy.copy(original)
# 深拷贝
deep = copy.deepcopy(original)
# 修改原对象的内部子对象
original[0][0] = 999
print("原对象:", original) # [[999, 2, 3], [4, 5, 6]]
print("浅拷贝:", shallow) # [[999, 2, 3], [4, 5, 6]] ← 浅拷贝被子对象修改影响
print("深拷贝:", deep) # [[1, 2, 3], [4, 5, 6]] ← 深拷贝完全独立图解对比
原对象 浅拷贝 深拷贝
│ │ │
├─ 外层容器 ──复制──→ 新外层容器 新外层容器
│ │ │
├─ 子对象A ←────共享────┘ │
│ └─ 复制子对象A → 新子对象A'
└─ 子对象B ←────共享────┘ └─ 复制子对象B → 新子对象B'
适用场景
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 一维容器(无嵌套) | copy() | 性能好,效果等同于深拷贝 |
| 嵌套容器且需要独立副本 | deepcopy() | 确保完全独立,互不影响 |
| 自定义对象 | 看需求 | 对象内部有可变属性时需深拷贝 |
| 性能敏感且只需顶层副本 | copy() | 深拷贝递归复制开销大 |
特殊情况
import copy
# 1. 一维列表:浅拷贝足够
a = [1, 2, 3]
b = copy.copy(a)
a[0] = 999
print(b) # [1, 2, 3] ← 不受影响(因为元素是不可变对象)
# 2. 元组不可变:copy 和 deepcopy 都返回原对象
t = (1, [2, 3]) # 元组内部有列表
t2 = copy.deepcopy(t)
t2[1][0] = 999 # 可以修改,因为是深拷贝的新列表
# 3. 循环引用:deepcopy 能处理
a = [1]
a.append(a) # 自引用
b = copy.deepcopy(a) # ✅ 正常工作,不会无限递归