update()就地修改原字典并返回none,|返回新字典且原字典不变;二者均为浅合并,不递归处理嵌套字典;update()支持多种输入格式,|仅接受dict;python 3.9+中|不可用于|=,且右操作数必须为dict。

字典合并时 update() 和 | 的行为根本不同
别被名字骗了:update() 是就地修改原字典,|(合并运算符)返回一个新字典,原字典完全不动。这是最常踩的坑——你以为在“合并”,其实一个在改旧数据,一个在造新数据。
-
update()返回None,不能链式调用;|返回dict,可连续写d1 | d2 | d3 - 嵌套字典不会递归合并:
update()和|都只做浅层覆盖,{"a": {"x": 1}} | {"a": {"y": 2}}结果是{"a": {"y": 2}},不是{"a": {"x": 1, "y": 2}} -
update()接受任意映射或键值对序列(比如update([('k', 'v')])或update(k='v')),而|只接受另一个dict实例
Python 3.9+ 用 | 合并多个字典的写法和限制
| 看起来像集合操作,但它是专为 dict 定义的,优先级低于算术运算符,所以 a | b | c 没问题,但 a | b.keys() 会报错——右边必须是 dict。
- 支持右操作数是
dict子类(如collections.OrderedDict),但结果总是dict类型 - 如果左边是空字典
{},右边是带重复键的字典,后出现的键值对胜出(和update()一致) - 不支持
|=就地更新(那是update()的活),d |= other在 Python 3.9+ 是语法错误 - 性能上,
|比多次update()略快,因为避免了中间状态修改,但差异通常可忽略
update() 在循环中误用导致数据污染
常见错误:把同一个字典对象反复 update() 到不同目标里,结果所有目标都指向同一份被改过的数据。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
base = {"name": "default"}
configs = []
for env in ["dev", "prod"]:
d = {}
d.update(base) # ✅ 浅拷贝没问题
d["env"] = env
configs.append(d)
<h1>但如果 base 里有可变对象:</h1><p>base = {"tags": ["a"]}
d1 = {}
d1.update(base)
d1["tags"].append("b") # ❌ 这会同时改掉 base["tags"]</p>
- 想安全复用含可变值的字典,得用
copy.deepcopy(),或者初始化时就构造新结构 -
update()不检查键是否存在,直接覆盖,容易掩盖逻辑错误(比如本该报错的重复配置项) - 调试时注意:打印
d前后,如果发现键变多了/少了,先查是不是update()被多调了一次
兼容旧版本 Python 的合并写法怎么选
如果你的代码要跑在 Python | 不可用,但别急着全换成 update()——它破坏原字典。更稳妥的是用 {**d1, **d2} 解包(Python 3.5+)或 dict(d1, **d2)(仅限字符串键)。
-
{**d1, **d2}最接近|行为:返回新字典、右键优先、支持任意键类型 -
dict(d1, **d2)快但危险:如果d2键不是字符串,运行时报TypeError - 三方库如
pyrsistent或toolz提供不可变合并,适合函数式风格,但引入依赖要权衡 - 别用
copy.copy(d1).update(d2):多一次拷贝,且仍需处理可变嵌套值
实际项目里,合并逻辑越靠近数据入口(比如配置加载、API 响应组装),越要明确是“新建”还是“修改”。一个 | 或一个 update() 看似只差一个字符,背后却是状态管理思路的分叉点。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










