copy.deepcopy 默认安全,因其通过 memo 缓存自动识别并跳过循环引用,避免无限递归;自定义 deepcopy 必须正确传入和使用 memo 参数,否则易引发栈溢出。

直接用 copy.deepcopy 就能防止内存溢出,它内部自带循环引用防护机制,不是靠“避免”而是靠主动识别和跳过重复对象。
核心原理是 memo 缓存copy.deepcopy 在执行过程中会维护一个 memo 字典,记录每个已处理对象的 id() 和对应副本。当再次遇到同一对象时,直接返回缓存副本,不再递归进入——这就从根源上切断了无限调用链。
常见错误反而会触发栈溢出
- 自定义
__deepcopy__时漏传memo参数 - 手动写递归拷贝函数,没做 visited 标记
- 用
eval(repr(obj))或json.dumps(obj)等不支持引用跟踪的方式替代深拷贝
正确做法很简单
import copy new_obj = copy.deepcopy(original_obj) # ✅ 默认安全,无需额外配置
自定义 __deepcopy__ 必须守规矩
如果类里重写了这个方法,要确保:
- 接收
memo参数 - 创建新实例后立刻注册到
memo中:memo[id(self)] = new_obj - 所有字段拷贝都显式传入
memo:copy.deepcopy(self.data, memo)
实在不行就换路径
- 对纯数据结构:转 JSON 再加载(
json.loads(json.dumps(obj, default=str))),彻底断引用,但丢方法和类型 - 对复杂对象(含函数、模块、C 扩展):用
dill库,它比pickle更强,原生支持循环引用 - 超深层嵌套且可控结构:改用迭代式拷贝(显式栈 + memo 字典),完全绕开系统调用栈限制
本质上这不是“防溢出”的补救措施,而是尊重 Python 已经做好的设计。只要不绕过 copy.deepcopy 的默认逻辑,循环引用不会导致崩溃。

















