浅拷贝无法切断嵌套对象的内层引用,修改副本会污染原对象;必须用copy.deepcopy()递归复制所有层级,但对numpy数组、文件句柄等需特殊处理,且性能开销大。

因为不 deep 拷贝,你改的不是副本,而是原对象本身——尤其在嵌套列表、字典或自定义类实例里,copy.copy() 或 list.copy() 无法切断内层引用。
修改嵌套列表时原对象被意外改动
这是最常踩的坑:你以为自己在操作副本,结果原始数据已污染。
- 现象:
original = [[1, 2], [3, 4]],用shallow = original.copy()后执行shallow[0].append(99),original也变成[[1, 2, 99], [3, 4]] - 原因:
.copy()只复制外层数组,两个列表的[0]仍指向同一子列表对象 - 验证方式:
id(shallow[0]) == id(original[0])返回True - 正确做法:必须用
import copy后调用copy.deepcopy(original)
含字典、集合、自定义类的嵌套结构必须用 deepcopy
浅拷贝对 dict、set、list 的顶层有效,但内部可变对象全部共享引用。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 典型场景:配置字典
config = {'db': {'host': 'localhost', 'port': 5432}, 'cache': [1, 2]},传给下游函数前想临时改config['db']['host'],用浅拷贝会污染全局配置 -
copy.deepcopy()会递归处理每一层,包括字典的值、集合元素、列表项里的对象 - 自定义类若含可变属性(如
self.items = []),默认deepcopy也能安全复制;但若含文件句柄、线程锁等不可序列化资源,需手动实现__deepcopy__(self, memo)
NumPy 数组和不可序列化对象是例外
copy.deepcopy() 不是万能钥匙,某些对象它要么慢、要么错、要么根本不能用。
-
numpy.ndarray:别用copy.deepcopy(arr),它可能破坏dtype、strides,甚至触发RecursionError;直接用arr.copy() - 文件对象、socket、数据库连接等:会抛出
TypeError: unshallowable object;这类资源本就不该被拷贝,应重新初始化 - 带
__slots__的类:默认deepcopy可能漏掉 slot 字段,需检查__dict__是否为空,必要时重写__deepcopy__
真正容易被忽略的点是:deepcopy 的代价藏在“递归”二字里——对象层级越深、含的可变子对象越多,它就越慢、越吃内存。如果只是单层数字列表,list[:] 或 list(original) 更快更轻量;只有当你明确要切断所有嵌套引用时,才值得付出这个开销。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










