copy.deepcopy能处理任意深度嵌套对象,但要求对象可序列化且不含不可拷贝成分(如线程锁、文件句柄);它因维护memo字典、逐层类型判断、构造新实例和递归处理而显著慢于浅拷贝。

直接说结论:copy.deepcopy 能处理任意深度嵌套的对象,但前提是对象可序列化且不包含不可拷贝的成分(比如文件句柄、线程锁、某些 C 扩展对象)。它不是万能的,用错地方反而会卡死或报错。
deepcopy 为什么比浅拷贝慢得多?
copy.deepcopy 不是递归调用那么简单——它会维护一个“已拷贝对象映射表”(memo dict),用来避免循环引用导致无限递归。每次遇到新对象,都要做类型判断、构造新实例、逐字段赋值、再递归处理子对象。这个过程涉及大量 Python 层对象创建和属性访问。
- 嵌套越深、对象越多,内存分配和字典查找开销越大
- 如果对象里有
__deepcopy__方法,会优先调用它,可能引入意外逻辑 - 遇到不可拷贝对象(如
socket.socket、threading.Lock)直接抛TypeError
哪些嵌套结构 deepcopy 会失败?
常见踩坑点不是“嵌套太深”,而是“里面有不能被 pickle 的东西”。比如:
- 函数对象(含闭包变量)→ 报
TypeError: can't pickle function objects - 模块对象、类对象本身 → 同样触发 pickle 失败
- 带
__slots__且没定义__getstate__的类实例 → 可能漏字段或报错 - NumPy 数组一般没问题,但某些自定义 dtype 或绑定 C 内存的数组会出问题
示例:
import copy
class BadClass:
def __init__(self):
self.f = lambda x: x + 1 # 函数闭包
<p>obj = BadClass()
copy.deepcopy(obj) # TypeError</p>
替代方案:什么时候不该用 deepcopy?
如果只是想隔离数据做计算,优先考虑更轻量的方式:
- 纯字典/列表嵌套 → 用
json.loads(json.dumps(obj))(快、安全、但只支持 JSON 基本类型) - 需要保留类型但结构固定 → 手动写
dict.copy()+ 递归遍历,控制哪些字段深拷,哪些浅拷或跳过 - 涉及 NumPy/Pandas → 用
.copy(deep=True),它们内部做了优化,不走通用 deepcopy - 有循环引用又必须深拷 → 确认对象实现了
__deepcopy__,或改用copyreg注册定制拷贝逻辑
真正难搞的不是嵌套层数,是对象图里混进了“活”的资源句柄或状态依赖。看清你要拷的是数据,还是带行为的运行时实体。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











