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) # 更新z字典,用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
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
17
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: {}}}
result = dict_of_dicts_merge(x, y)
print(result) # 输出: {'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}

最佳实践

性能考虑

在选择合并字典的方法时,性能是一个重要的考虑因素。通过 timeit 模块进行性能测试,以下是不同方法的性能比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from timeit import repeat
from itertools import chain

x = dict.fromkeys('abcdefg')
y = dict.fromkeys('efghijk')

def merge_two_dicts(x, y):
z = x.copy()
z.update(y)
return z

print(min(repeat(lambda: {**x, **y})))
print(min(repeat(lambda: merge_two_dicts(x, y))))
print(min(repeat(lambda: {k: v for d in (x, y) for k, v in d.items()})))
print(min(repeat(lambda: dict(chain(x.items(), y.items())))))
print(min(repeat(lambda: dict(item for d in (x, y) for item in d.items()))))

在Python 3.8.1中,测试结果表明 {**x, **y}x | y(Python 3.9+) 通常是最快的方法。

代码可读性

代码的可读性也很重要。对于简单的合并需求,使用 {**x, **y}x | y 是简洁且易于理解的。对于需要自定义合并逻辑的场景,编写自定义函数可以提高代码的可读性和可维护性。

常见问题

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

在Python 2中,使用 dict(x.items() + y.items()) 会创建多个列表,消耗额外的内存。在Python 3中,dict_items 对象不能直接相加,需要先转换为列表,这会导致性能问题。示例代码如下:

1
2
3
4
5
# Python 3 中会报错
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
# 以下代码会报错
# z = dict(x.items() + y.items())

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

dict(x, **y) 这种方法在Python 3中,如果 y 中的键不是字符串,会引发 TypeError 异常。并且这种方法的可读性较差,不建议使用。示例代码如下:

1
2
3
4
x = {'a': 1}
y = {('b',): 2}
# 以下代码会报错
# z = dict(x, **y)

合并嵌套字典时的问题

上述介绍的简单合并方法通常只进行浅合并,对于嵌套字典,内部的嵌套字典会被直接覆盖,而不是递归合并。如果需要递归合并嵌套字典,可以使用前面提到的 dict_of_dicts_merge 函数。


Python中合并两个字典的方法
https://119291.xyz/posts/2025-04-16.python-dictionary-merging-methods/
作者
ww
发布于
2025年4月16日
许可协议