HOWTO · Python

如何在 Python 2 和 3 中合併兩個字典

本教程介紹瞭如何在 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}