Python合并字典的高效优雅方案:从Python 3.5到旧版本的最佳实践

月亮慢半拍
月亮慢半拍
发布时间:2026-10-13| 3人浏览过
原创

本文深入探讨Python中合并两个字典的多种方法,重点介绍Python 3.5引入的**{**x, **y}解包语法,以及适用于Python 2和早期Python 3版本的优雅替代方案。通过对比items()、构造函数及itertools.chain等方法的性能与兼容性,帮助开发者根据版本需求选择最高效且Pythonic的实现方式。

前言

字典(dict)是Python中极为强大且常用的数据类型。本文将详细解析合并两个字典的多种实现方式,分享实用技巧供读者参考。

一行代码合并两个字典

假设存在两个字典变量x和y,我们需要生成一个新的字典z,且在此过程中不修改原始的x和y。例如:

 x = {'a': 1, 'b': 2}
 y = {'b': 3, 'c': 4}

期望生成的新结果z中,若存在相同的键(key),则y中的值将覆盖x中的值。期望的最终结果为:

>>> z
{'a': 1, 'b': 3, 'c': 4}

在PEP 448规范中,引入了新的语法支持,该语法自Python 3.5版本起可用。合并代码如下:

z = {**x, **y}

这确实是一行代码的简洁写法。鉴于目前仍有不少用户在使用Python 2,或者处于Python 3.0至3.4版本之间,对于这些用户而言,存在一种较为优雅但需要两行代码的替代方案。

z = x.copy()
z.update(y)

上述方法中,y的值会覆盖x中对应的内容,因此最终结果中b的值为3。

如何在未使用Python 3.5的情况下实现一行代码合并?

如果您尚未升级至Python 3.5,或者需要编写向后兼容的代码,同时希望保持单行表达式的简洁性,最高效的方法是将逻辑封装在一个函数中:

def merge_two_dicts(x, y):
 """Given two dicts, merge them into a new dict as a shallow copy."""
 z = x.copy()
 z.update(y)
 return z

随后,只需一行代码即可调用该函数完成合并:

 z = merge_two_dicts(x, y)

您还可以定义一个函数来合并多个字典,示例如下:

def merge_dicts(*dict_args):
 """
 Given any number of dicts, shallow copy and merge into a new dict,
 precedence goes to key value pairs in latter dicts.
 """
 result = {}
 for dictionary in dict_args:
 result.update(dictionary)
 return result

使用方式如下:

z = merge_dicts(a, b, c, d, e, f, g)

在所有上述方法中,处理相同键(key)时,均遵循“后者优先”的原则,即后面的字典值会覆盖前面的值。

以下展示一些不够优雅的实现方式:

利用items()方法

部分开发者可能会采用这种方法:

 z = dict(x.items() + y.items())

这种做法实际上是在内存中创建了两个列表,进而创建第三个列表,拷贝完成后再生成新字典,最后删除前三个列表。此过程耗费性能,且在Python 3中无法直接执行,因为items()返回的是视图对象而非列表。

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict_items' and 
'dict_items'

您必须显式将其转换为列表,即z = dict(list(x.items()) + list(y.items())) ,这严重浪费了性能。此外,依赖items()返回的列表进行并集操作的方法在Python 3中同样会失败。更关键的是,并集操作导致重复键在取值时具有不确定性。因此,如果您对字典合并的优先级有明确要求,这种方法完全不可取。

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

这里有一个示例,其中y本应具有更高优先级,但由于集合顺序的任意性,x的值被意外保留:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

利用构造函数

也有人会使用以下方式:

z = dict(x, **y)

这种方式虽然比前述两步法高效,但可读性较差,不够Pythonic。特别是在键(key)非字符串类型时,Python 3中运行会失败。

>>> c = dict(a, **b)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

Python创始人Guido van Rossum指出,宣告dict({}, {1:3})为非法操作,因为这属于滥用机制。尽管这种方法颇具黑客风格,但过于投机取巧,不推荐在正式代码中使用。

一些性能稍逊但相对优雅的方法

以下方法虽然性能不如最优解,但远优于items()方法,且支持优先级控制。

{k: v for d in dicts for k, v in d.items()}

在Python 2.6中可以使用以下方式:

 dict((k, v) for d in dicts for k, v in d.items())

itertools.chain可以将键值对的迭代器按正确顺序链接:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

性能测试

以下测试在Ubuntu 14.04系统下的Python 2.7(系统默认Python)环境中完成:

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(),y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

在Python 3.5环境下的测试结果:

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

总结

以上就是本文的全部内容,希望这些内容能对您的学习或工作有所帮助。如有任何疑问,欢迎留言交流,感谢大家的支持。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。