bigywater.tech
Python · 14

浅拷贝与深拷贝:deepcopy 到底复制了什么

用嵌套列表验证修改原始对象的内层元素时,浅拷贝会不会跟着变、深拷贝会不会独立,并用id()确认背后的对象关系。

外层独立内层共享
浅拷贝的对象关系
全部独立
深拷贝递归复制的结果
嵌套才显现差异
扁平不可变数据两者等价

做的事:一个嵌套列表,改内层元素看两种拷贝的反应

copy.copy是浅拷贝,copy.deepcopy是深拷贝,差别只在"嵌套"结构上才会显现。

代码original = [[1, 2, 3], [4, 5, 6]] shallow = copy.copy(original) deep = copy.deepcopy(original) original[0].append(999) -- 修改original内层的子列表

验证:改了原始对象的内层,浅拷贝跟着变了

三个变量,同一次修改,看到两种不同的反应。

结果修改original[0]后: original = [[1, 2, 3, 999], [4, 5, 6]] shallow = [[1, 2, 3, 999], [4, 5, 6]] ← 也跟着变了! deep = [[1, 2, 3], [4, 5, 6]] ← 完全没受影响

结果一目了然:只修改了 original,shallow 也跟着变了,deep 纹丝不动。

验证:用id()确认浅拷贝的内层元素是同一个对象

现象背后,的对象关系是什么样的。

结果original is shallow: False(外层是不同对象) original[1] is shallow[1]: True(内层元素是同一个对象!) original[1] is deep[1]: False(deepcopy连内层也复制了新对象)

的对象关系是:copy.copy() 只创建了一个新的外层列表容器,但容器里装的元素(这里是两个内层子列表)还是原来那两个对象,只是被两个不同的外层列表同时引用着——改动内层子列表,两边看到的自然是同一份数据。copy.deepcopy() 则是递归地把外层、内层全部都创建了新对象,原始对象和深拷贝之间没有任何共享的可变对象。

这解释了为什么浅拷贝"看起来像拷贝了,用起来却像没拷贝"——只有当你的数据结构是"一层的、元素都是不可变类型"(比如纯数字/字符串的列表)时,浅拷贝才等价于深拷贝;一旦出现嵌套的可变对象(列表套列表、字典里存列表等),浅拷贝就只隔离了最外面那一层,内部数据依然共享,必须用deepcopy才能真正得到一份独立的副本。

分步演示:浅拷贝和深拷贝的对象关系

每一步都是本文上面用Python 3.14跑出来的原始结果。

浅拷贝只隔离最外层,内层元素是同一个对象
这一步新验证的结果

    本文用到的工具

    • 本机 Python 3.14.7
    • copy.copy / copy.deepcopy:对比嵌套结构下的拷贝行为
    • is / id():验证内层元素是否共享同一个对象
    京ICP备2026067502号-1京公网安备11010502063487号