Python 字典浅拷贝:为什么嵌套列表会一起变化?

举报
yd_239549656 发表于 2026/11/01 08:04:01 2026/11/01
【摘要】 用同一份嵌套字典演示赋值、dict.copy 和 deepcopy 的区别,区分替换外层字段与修改内层列表,并说明测试范围。

对字典调用 copy() 后,只给“副本”的标签列表追加一个值,原字典却也变了。这不一定是复制失败,而是需要先区分外层字典和它引用的内层对象。

1. 用一个完整样例观察

下面的数据完全在程序里构造,不读取业务文件:

from copy import deepcopy

original = {"tags": ["python"], "enabled": True}
alias = original
print("赋值共享:", alias is original)

shallow = original.copy()
print("外层独立:", shallow is not original)
print("内层共享:", shallow["tags"] is original["tags"])

shallow["enabled"] = False
shallow["tags"].append("csv")
print("原始数据:", original)

deep = deepcopy(original)
deep["tags"].append("json")
print("深拷贝后的原列表:", original["tags"])
print("深拷贝后的新列表:", deep["tags"])

本样例得到:

赋值共享: True
外层独立: True
内层共享: True
原始数据: {'tags': ['python', 'csv'], 'enabled': True}
深拷贝后的原列表: ['python', 'csv']
深拷贝后的新列表: ['python', 'csv', 'json']

2. 看清发生变化的位置

alias = original 只是让两个名字指向同一个字典。

original.copy() 则创建了新的外层字典。因此,给 shallow[“enabled”] 重新赋值,不会替换 original 里的同名字段。

但浅拷贝中的 tags 仍然引用同一个列表。append 修改的是这个共享列表,所以原字典也看得到新增的 csv。判断“原数据为什么变了”时,应先区分重新绑定字段和修改字段引用的对象。

这也说明,只检查 shallow is not original 还不够。若业务要求嵌套数据独立,还需要检查要修改的内层对象。

3. deepcopy 解决的是本例的嵌套共享

本例用 deepcopy 创建了另一份嵌套列表,给 deep[“tags”] 追加 json 后,original[“tags”] 保持不变。

这不意味着任何场景都应该把 copy 换成 deepcopy。代码如果只替换外层字段,浅拷贝可能已经满足需要;如果某些对象本来就应共享,递归复制也可能偏离设计。Python 官方 copy 文档说明了两种复制方式及自定义对象的复制协议。

4. 明确验证范围

本次在本机 Python 3.9.6 中执行了八项断言:赋值引用相同、浅拷贝外层独立、浅拷贝内层共享、外层字段独立、共享列表变更、深拷贝列表独立、深拷贝后原列表保持不变、深拷贝新列表符合预期。

样例只覆盖字典、列表、字符串和布尔值,没有测试自定义对象、文件、网络连接或性能开销。遇到这些对象时,应另外确认其复制语义,不把教学样例当成完整的对象复制方案。

官方参考:docs.python.org/3/library/copy.html。

本文由 AI 辅助整理,示例使用独立构造的数据并已在本机执行自检。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。