浅拷贝只复制外层容器,嵌套可变对象仍共享引用,修改子列表会导致原对象变化;深拷贝递归复制所有层级,完全隔离,但性能开销大;不可变对象无需拷贝,Python自动共享。

浅拷贝修改嵌套列表时原对象跟着变
因为 copy.copy() 只复制最外层容器,内部可变对象(比如列表里的子列表)仍是同一份引用。改子列表,原对象就同步变化。
常见错误现象:original = [[1, 2], [3]]; shallow = copy.copy(original); shallow[0].append(99); print(original) → 输出 [[1, 2, 99], [3]],不是预期的不变。
- 适用场景:只有一层结构、全是不可变元素(如
[1, 'a', True]),或明确知道不会修改嵌套内容 - 性能更好:不递归遍历,开销小
- 注意
list.copy()、[:]、list(original)都是浅拷贝,不是“真复制”
深拷贝能真正隔离嵌套可变对象
copy.deepcopy() 会递归复制所有层级的可变对象,确保新旧对象内存完全独立。改拷贝体,原对象绝对不受影响。
使用场景:数据结构含多层嵌套(如 JSON-like 字典、树形列表)、需要安全传递/修改副本而不污染源头。
立即学习“Python免费学习笔记(深入)”;
- 参数无额外选项,但支持自定义
__deepcopy__方法控制行为 - 性能代价明显:递归 + 检查循环引用,大数据量或深层嵌套时明显变慢
- 不支持无法序列化的对象(如文件句柄、线程锁),会抛
TypeError
不可变对象根本不需要拷贝
字符串、整数、元组(且内部全不可变)在 Python 中是共享引用的,copy.copy() 或 copy.deepcopy() 对它们都返回原对象本身——因为改不了,也无需隔离。
例如:a = (1, 2); b = copy.copy(a); a is b 返回 True;id(a) == id(b) 也成立。
- 元组含可变项(如
([],))则另当别论:外层不可变,但内层列表仍可被修改,此时必须用深拷贝才安全 - 别为提升性能刻意避免拷贝不可变对象——Python 已经帮你做了最优处理
自定义类里要小心 __dict__ 和循环引用
默认情况下 copy.deepcopy() 通过 __dict__ 复制实例属性,但如果类里有函数、模块、类对象或弱引用,可能出错或行为异常。
更麻烦的是循环引用:a = []; b = [a]; a.append(b) 这种结构,深拷贝必须检测并重建引用链,否则无限递归。
- 若需精确控制,实现
__copy__(self)和__deepcopy__(self, memo)方法 -
memo是字典,记录已拷贝对象的 id 映射,用于破循环;手动实现时务必传给子对象的deepcopy - 没重写
__deepcopy__却含 C 扩展对象(如 NumPy 数组),可能跳过深拷贝逻辑,导致意外共享
deepcopy;不改,或者只有一层,copy 或切片够用。最常被忽略的是元组和自定义类——表面 immutable,里面藏了个 list,一改就穿帮。










