Python 中的浅拷贝 vs 深拷贝:面向面试的解释
发布: (2025年12月23日 GMT+8 21:41)
5 min read
原文: Dev.to
Source: Dev.to
Introduction
最常见的 Python 面试题之一听起来貌似很简单:
“Python 中浅拷贝和深拷贝有什么区别?”
面试官通过这个问题来考察:
- 对可变对象与不可变对象的理解
- 对对象引用的把握
- 推理副作用和 bug 的能力
- 对真实 Python 行为的认识(而不仅仅是定义)
这在后端、数据和机器学习岗位尤为重要。
浅拷贝
浅拷贝 会创建一个新的容器对象,但 不会 递归地复制其中的对象。外层对象被复制,而内部对象仍然是共享的引用。
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original)
shallow[0].append(99)
print(original) # [[1, 2, 99], [3, 4]]
print(shallow) # [[1, 2, 99], [3, 4]]
original和shallow是不同的列表,但它们内部的列表指向同一块内存。
深拷贝
深拷贝 会创建一个新的容器 并且 递归复制所有嵌套对象,从而没有共享的引用。复制得到的结构是完全独立的。
import copy
original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
deep[0].append(99)
print(original) # [[1, 2], [3, 4]]
print(deep) # [[1, 2, 99], [3, 4]]
- 对
deep的更改不会影响original。
类比
- 浅拷贝 → 复制盒子本身,而不是里面的项目。
- 深拷贝 → 复制盒子 以及 里面的所有内容。
这种类比有助于在面试中快速传达概念。
Python 中常见的复制方式
| Operation | Type of Copy | Note |
|---|---|---|
list.copy() | 浅拷贝 | |
list[:] | 浅拷贝 | 切片始终是浅拷贝 |
dict.copy() | 浅拷贝 | |
copy.copy(obj) | 浅拷贝 | |
copy.deepcopy(obj) | 深拷贝 | 更耗时且占用更多内存 |
b = a | 无复制 | 简单赋值共享同一对象 |
重要陷阱
-
误解: “浅拷贝一次就复制了所有内容。”
- 实际情况: 嵌套的可变对象仍然是共享的。
-
深拷贝的代价:
- 执行速度更慢
- 内存占用更高
- 可能破坏对对象身份的假设
-
不可变对象(例如
int、str、tuple)不会导致共享状态问题。
何时避免深拷贝
- 对性能有要求的大型、深层嵌套结构
- 持有外部资源的对象(文件、数据库连接)
- 在可以接受受控共享数据变更的情形下
自定义复制行为
高级面试候选人可能会提到,自定义类可以通过实现以下方法来控制复制:
def __copy__(self):
# return a shallow copy of the instance
...
def __deepcopy__(self, memo):
# return a deep copy of the instance
...
这表明了高级水平的理解,因为许多框架依赖这些钩子。
Structured Answer to the Interview Question
浅拷贝创建一个新的容器,但对嵌套对象共享引用,而深拷贝则递归地复制所有对象。浅拷贝速度更快且节省内存,但在可变的嵌套数据上可能导致副作用。深拷贝避免共享状态,但代价更高。Python 提供
copy.copy()用于浅拷贝,copy.deepcopy()用于深拷贝。
实际复制相关的错误
- 共享引用: 在一个副本中修改嵌套对象会意外影响另一个副本。
- 假设独立性: 将浅拷贝视为完全独立会导致细微错误。
了解这些错误产生的原因,可帮助你在面试场景和生产代码中都自信应对。