如何在Python中用单个表达式合并两个字典

如何在Python中用单个表达式合并两个字典

技术背景

在Python编程中,经常会遇到需要合并两个字典的场景。我们期望将两个字典合并成一个新的字典,且不改变原始字典,同时后一个字典的值能覆盖前一个字典中相同键的值。不同Python版本提供了不同的方法来实现这一需求。

实现步骤

Python 3.9.0 及更高版本

在Python 3.9.0及更高版本中,可以使用 | 操作符来合并两个字典。示例代码如下:

1
2
3
4
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = x | y
print(z) # 输出: {'a': 1, 'b': 3, 'c': 4}

Python 3.5 及更高版本

在Python 3.5及更高版本中,可以使用字典解包语法 {**x, **y} 来合并两个字典。示例代码如下:

1
2
3
4
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = {**x, **y}
print(z) # 输出: {'a': 1, 'b': 3, 'c': 4}

Python 2 或 3.4 及更低版本

在Python 2或3.4及更低版本中,需要编写一个函数来实现字典的合并。示例代码如下:

1
2
3
4
5
6
7
8
9
def merge_two_dicts(x, y):
z = x.copy() # 从x的键值对开始
z.update(y) # 用y的键值对修改z
return z

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge_two_dicts(x, y)
print(z) # 输出: {'a': 1, 'b': 3, 'c': 4}

核心代码

合并任意数量的字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def merge_dicts(*dict_args):
"""
给定任意数量的字典,浅拷贝并合并到一个新的字典中,
后面字典的键值对优先级更高。
"""
result = {}
for dictionary in dict_args:
result.update(dictionary)
return result

a = {'a': 1}
b = {'b': 2}
c = {'c': 3}
z = merge_dicts(a, b, c)
print(z) # 输出: {'a': 1, 'b': 2, 'c': 3}

递归合并字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from copy import deepcopy

def dict_of_dicts_merge(x, y):
z = {}
overlapping_keys = x.keys() & y.keys()
for key in overlapping_keys:
z[key] = dict_of_dicts_merge(x[key], y[key])
for key in x.keys() - overlapping_keys:
z[key] = deepcopy(x[key])
for key in y.keys() - overlapping_keys:
z[key] = deepcopy(y[key])
return z

x = {'a': {1: {}}, 'b': {2: {}}}
y = {'b': {10: {}}, 'c': {11: {}}}
print(dict_of_dicts_merge(x, y)) # 输出: {'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}

最佳实践

  • 优先使用 | 操作符(Python 3.9+)或 {**x, **y} 语法(Python 3.5+),因为它们简洁且性能较好。
  • 如果需要兼容旧版本Python,可以编写函数使用 copyupdate 方法。
  • 当需要合并多个字典时,使用 merge_dicts 函数。
  • 当需要递归合并嵌套字典时,使用 dict_of_dicts_merge 函数。

常见问题

使用 dict(x.items() + y.items()) 的问题

在Python 2中,会在内存中为每个字典创建两个列表,再创建一个长度等于前两个列表之和的新列表,最后丢弃这三个列表来创建字典,浪费资源和计算能力。在Python 3中,会因为 dict_items 对象不能相加而失败。示例代码如下:

1
2
3
4
5
6
7
# Python 3
a = {'a': 1}
b = {'b': 2}
try:
c = dict(a.items() + b.items())
except TypeError as e:
print(e) # 输出: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

使用 dict(x, **y) 的问题

这种方法要求 y 的键必须是字符串,否则在Python 3中会报错。示例代码如下:

1
2
3
4
5
6
7
# Python 3
a = {'a': 1}
b = {('a', 'b'): 2}
try:
c = dict(a, **b)
except TypeError as e:
print(e) # 输出: keyword arguments must be strings

合并嵌套字典的问题

{**x, **y}x | y 只能进行浅合并,对于嵌套字典,内部嵌套的键值对会被直接覆盖,而不是递归合并。如果需要递归合并嵌套字典,可以使用 dict_of_dicts_merge 函数。


如何在Python中用单个表达式合并两个字典
https://119291.xyz/posts/2025-05-07.how-to-merge-two-dictionaries-in-python-with-a-single-expression/
作者
ww
发布于
2025年5月7日
许可协议