如何在 Python 2 和 3 中合并两个字典
假设我们有两个字典 A
和 B
需要进行合并,其中 B
的值将取代 A
的值,如果它们有相同的键 key
的话。
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
Python dictionary
对象有一个原生方法 update()
来用 B
来更新字典 A
,
A.update(B)
但是 A
的数据将被替换,而不是返回包含合并 A
和 B
的新字典。
我们将介绍如何合并两个字典并返回新字典的方法。
Python 2.7 字典合并
字典推导式方法-1
C = {key: value for d in (A, B) for key, value in d.items()}
d.itmes()
以字典 d
的 2 元组的形式返回 (key, value)
对的列表。
此方法使用嵌套字典推导式合并两个字典。for
的正确顺序应格外注意。它应该是,
flattern_patterns = [planet
for sublist in planets
for planet in sublist]
字典推导式方法-2
我们还可以使用 dict()
方法来初始化新字典。
C = dict((key, value) for d in (A, B) for key, value in d.items())
从技术上讲,它与上述方法几乎相同,但是在性能上有所不同,我们将在后面提到。
itertools.chain
方法
itertools
模块标准化了一组核心 iterator
构建块。它具有快速和高效存储等功能。
itertools.chain
返回一个链对象,该对象的 .next()
方法从第一个可迭代对象返回元素,直到用尽为止,然后从下一个可迭代对象返回元素,直到所有元素用尽。
dict(itertools.chain(A.iteritems(), B.iteritems()))
iteritems()
返回字典 (key, value)
元素的迭代器。
因此,以上脚本将返回包含 A
和 B
元素的字典。
copy
和 update
方法
如开头所述,update
可以合并 A
和 B
,但是将就地替换字典。我们可以使用 copy
方法复制字典 A
。
m = A.copy()
C = m.update(B)
合并方法性能分析和比较
import timeit
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''
TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))
TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))
TEST_CODE = '''
dict(itertools.chain(A.iteritems(), B.iteritems()))
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))
SETUP_CODE = '''
def merge_dicts(a, b):
m = a.copy()
m.update(b)
return m
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''
TEST_CODE = '''
merge_dicts(A, B)
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))
结果是
0.0162378
0.029774
0.019975
0.0110059
方法 | 性能 | 排名 |
---|---|---|
{key: value for d in (A, B) for key, value in d.items()} |
0.0162378 | 2 |
dict((key, value) for d in (A, B) for key, value in d.items()) |
0.029774 | 4 |
dict(itertools.chain(A.iteritems(), B.iteritems())) |
0.019975 | 3 |
merge_dicts(a, b) |
0.0110059 | 1 |
Python 3.5(及更高版本)字典合并方法
从 Python 3.5 开始,除了与 Python 2.7 中相同的方法外,它还具有 PEP-448 中 引入的 **
unpacking 运算符。它可以解压缩任意数量的 dictionary
对象。
d.iteritems()
在 Python 3 中已弃用。请参阅 PEP-469>>> C = {**A, **B}
>>> C
{'x': 10, 'y': 30, 'z': 40}
import timeit
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''
TEST_CODE = '''
{**A, **B}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
TEST_CODE = '''
dict(itertools.chain(A.items(), B.items()))
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
SETUP_CODE = '''
def merge_dicts(a, b):
m = a.copy()
m.update(b)
return m
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''
TEST_CODE = '''
merge_dicts(A, B)
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
0.0017047999999999508
0.009127499999999955
0.0168952
0.01078009999999996
0.005767999999999995
方法 | 性能 | 排名 |
---|---|---|
{**A, **B} |
0.0017047999999999508 | 1 |
{key: value for d in (A, B) for key, value in d.items()} |
0.009127499999999955 | 3 |
dict((key, value) for d in (A, B) for key, value in d.items()) |
0.0168952 | 5 |
dict(itertools.chain(A.items(), B.items())) |
0.01078009999999996 | 4 |
merge_dicts(a, b) |
0.005767999999999995 | 2 |
合并方法结论
在 Python 2.7,copy
和 update
是最好的方法。
m = A.copy()
C = m.update(B)
在 Python 3.5+ 中,字典解压缩方法是最好的。
{**A, **B}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn