Python 3.9中合并字典的浅拷贝行为如何处理_理解管道符操作的底层逻辑

风辰大大_2021

风辰大大_2021

2026-05-23

330人浏览

原创

字典合并|运算符仅做浅层键值叠加,不递归处理嵌套结构,右侧值直接覆盖左侧同键值(如{'x': {'a':1}} | {'x': {'b':2}}得{'x': {'b':2}}),且不深拷贝,嵌套可变对象仍共享引用。

python 3.9中合并字典的浅拷贝行为如何处理_理解管道符操作的底层逻辑

字典合并 | 运算符不触发深拷贝,只做浅层键值叠加

它根本不会递归复制嵌套结构,所有值都按引用直接搬过去。比如 {'x': {'a': 1}} | {'x': {'b': 2}} 的结果是 {'x': {'b': 2}},不是 {'x': {'a': 1, 'b': 2}}——右侧整个值对象替换了左侧的,连浅拷贝都不做。

常见错误现象:

  • 你本想“合并配置”,却意外丢失了左字典里某个嵌套字典的全部字段
  • 修改合并后字典中某嵌套字典的值,发现原始字典也被改了(因为引用同一对象)

使用场景:适合扁平配置拼接(如 API 参数、环境变量),不适合处理含可变嵌套结构的数据。

空字典参与 | 运算时实际发生的是浅拷贝

{} | d 等价于 d.copy(),不是 dict(d) 或 copy.deepcopy(d)。这意味着如果 d 的某个值是列表或嵌套字典,新字典里依然指向同一个对象。

容易踩的坑:

  • 误以为 {} | d 是“安全隔离”,结果后续修改嵌套值污染了原 d
  • 在函数返回值中用 defaults | user_input,但 user_input 里带 ['tag1', 'tag2'],调用方 later 修改这个列表,影响了其他地方缓存的配置副本

参数差异:该行为与 dict(d) 相同(仅限字符串键),但比 {**d} 更明确——后者在 Python 3.5+ 就存在,而 {} | d 是 3.9+ 才有且语义统一。

| 和 |= 都不解决可变默认值引发的共享引用问题

它们只是把键值对“贴”过去,不会检测值是否可变,更不会自动 .copy()。如果你写:

Forge — Python Developer
Forge — Python Developer

Python开发助手 — 自动化脚本、API封装、命令行工具、数据管道、网页爬虫。经过测试的代码,包含错误处理和文档。当你需要...

下载
base = {'flags': []}
d1 = base | {'name': 'a'}
d2 = base | {'name': 'b'}
d1['flags'].append('x')

你会发现 d2['flags'] 也变成了 ['x'],因为 base['flags'] 是同一个列表对象,被两个结果字典共用。

正确做法:

  • 初始化时就避免可变默认值:base = {'flags': []} → 改成 base = {'flags': None},后续用时再 .copy() 或新建
  • 需要独立副本,显式调用:base | {'flags': base.get('flags', []).copy()}
  • 或者封装为函数,内部做浅拷贝:lambda d: {k: v.copy() if isinstance(v, dict) else v for k, v in d.items()}

性能影响:每次手动 .copy() 增加开销,但比起意外的逻辑 bug,这点成本值得付。

Python 3.8 及以下版本无法降级兼容 | 运算符

这不是语法警告,而是硬性报错:SyntaxError: invalid syntax。CI 流水线、旧版 Docker 镜像、某些 IDE 的语法检查器(如 PyCharm 2021.3 之前)都会直接失败。

调试时注意:

  • 别在报错行反复检查括号或冒号——问题在解释器版本
  • 用 python --version 确认运行时版本,不是开发机版本
  • 若必须多版本兼容,用 {**d1, **d2} 替代 d1 | d2;用 d1.update(d2) 替代 d1 |= d2,但要意识到前者不返回值、后者会修改原字典

真正容易被忽略的点:| 运算符的“不可变性”是假象——它只保证不改输入字典的键值映射关系,但对值对象本身完全放手。嵌套可变对象的生命周期和所有权,仍得靠人来管。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1731

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4424

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1709

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

25997

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3147

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3167

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1183

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2463

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习