这样合并Python字典,可以让程序的运行效率提高4倍
摘要:在Python中,合并字典有多種方式,通過內建函數、運算符、自定義函數等,都可以完成合并字典的功能,但這些方式,哪些效率低,哪些效率高呢?本文將對這些合并字典的方式進行逐個深度詳解,最后會比較這些方式,看看到底誰是效率之王!
現在提出一個問題:如何用一行代碼合并兩個Python字典,并返回合并結果。可能很多同學最先想到的是下面的代碼:
x = {'a': 1, 'b': 2} y = {'b': 10, 'c': 11} x.update(y) # {'a': 1, 'b': 10, 'c': 11} print(x)這段代碼沒有任何問題,通過update方法可以將x和y合并,但問題是update方法修改了x的值,將合并的結果賦給了x,而不是新生成一個變量。這樣并沒有通過一行代碼合并兩個字典,而且還修改了變量x的值。
當然,我們可以做一些改變,例如,先定義一個空的字典z,然后分別將x和y與z合并,代碼如下:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' x = {'a': 1, 'b': 2} y = {'b': 10, 'c': 11} z = {} z.update(x) z.update(y) # {'a': 1, 'b': 10, 'c': 11} print(x)這段代碼完美地將x和y合并,而且并未改變x和y的值,不過代碼量比較多,仍然未使用一行代碼合并兩個字典。
下面就看看那些用一行代碼解決合并字典的方法們:
1. Python 3.9的解決方案
如果讀者使用Python 3.9,那簡直太幸運了,因為Python 3.9可以直接通過“|”運算符合并兩個字典,簡直干凈利索,代碼如下:
z = x | y print(z)不過遺憾的是,“|”運算符只能合并字典,不能合并列表。
2. Python 3.5及以上版本的解決方案
如果讀者使用的不是Python 3.9,但卻是Python3.5或以上版本,如Python3.7、Python3.8等,可以采用雙星(**)運算符合并兩個字典,代碼如下:
x = {'a': 1, 'b': 2} y = {'b': 10, 'c': 11} z = {**x, **y} print(z)這里的“**”表示將字典拆成key-value對形式傳入,那么{**x, **y}就表示先將x和y拆成獨立的key-value對,然后再將這些key-value對覆蓋新字典。
除了**外,還有可以處理列表的*,例如,下面的代碼可以合并兩個列表。合并原理與**類似。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' xx = [1,2,3] yy = [4,5,6] # 合并列表 zz = {*xx,*yy} print(zz)3. Python 3.4或一下版本的解決方案
如果讀者使用的是Python3.4或更低的Python版本,如Python2.7,那么如果想用一行代碼解決問題,就要自己編寫函數了。基本的解決思路是先將x整個復制一份,變成z,然后再使用update函數合并z與y。實現代碼如下:
def merge_two_dicts(x, y):z = x.copy() # 復制x到zz.update(y) # 將z與y合并,z已經改變return z現在就可以使用下面的一行代碼合并x和y了,而且x和y都沒有改變。
print(merge_two_dicts(x,y))如果還想合并不定數量的字典,如3個字典、5個字典,可以使用下面的函數:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def merge_dicts(*dict_args): result = {}for dictionary in dict_args:result.update(dictionary)return resultnew_dict = {'x':20,'y':30} # {'a': 1, 'b': 10, 'c': 11, 'x': 20, 'y': 30} print(merge_dicts(x,y,new))4. 深度合并
前面給出的案例只能淺層合并,如果想深度合并,可以使用遞歸的方式。例如,要合并下面兩個字典:
這兩個字典的每一個key,也是一個字典,現在需要合并每一個key表示的字典,合并的結果希望是如下形式:
{'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}要完成這個功能,需要使用deepcopy函數,代碼如下:
from copy import deepcopydef dict_of_dicts_merge(x, y):z = {}# 如果兩個要合并的字典結構不一致,無法合并,返回Noneif not hasattr(x,'keys') or not hasattr(y,'keys'):return# 交集:boverlapping_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現在可以使用下面的代碼合并xx和yy:
xx = {'a':{1:{}}, 'b': {2:{}}} yy = {'b':{10:{}}, 'c': {11:{}}} print(dict_of_dicts_merge(xx, yy))如果要合并的兩個字典的key對應的value,有一個不是字典,那么無法合并,在這種情況下,value就為None,例如,要合并下面兩個字典:
xx = {'a':{1:{}}, 'b': {2:{}}} yy = {'b':20, 'c': {11:{}}} print(dict_of_dicts_merge(xx, yy))由于yy的b是20,而xx的b是一個字典,所以b無法合并,因此執行這段代碼,會輸出如下結果:
{'b': None, 'a': {1: {}}, 'c': {11: {}}}5. 其他合并字典的方式
除了前面介紹的幾種合并字典的方式,還可以用下面的2種合并方式:
(1)for in 表達式
在Python中有一種語法,可以利用for in表達式生成列表或字典,因此,可以利用這個功能,將要合并的兩個字典中的key和value單獨提取出來,然后逐個寫入新的字典,實現代碼如下:
要理解for in表達式是如何工作的,可以先提取下面的代碼:
for d in(x,y) :print(d)這段代碼其實是將x和y作為元組的元素,輸出的結果如下:
{'a': 1, 'b': 2} {'b': 10, 'c': 11}然后for k, v in d.items()就是對這個元組進行迭代,而k和v就是提取元組中每一個元素的key和value,然后再將k和v作為新字典的key和value插入。
(2)使用chain對象
通過chain對象,可以將多個字典轉換為像鏈表一樣的結果(這個鏈表是可迭代的),然后再使用dict對象將其轉換為字典,實現代碼如下:
from itertools import chain x = {'a': 1, 'b': 2} y = {'b': 10, 'c': 11} print(dict(chain(x.items(), y.items())))6. 性能大比拼
到現在為止,已經講了很多種合并字典的方式,那么這些方式哪些效率高,哪些效率低呢?下面就來做一個實驗。
其中repeat函數可以用來方便地測試一小段代碼的執行時間,在默認情況下,repeat函數會將由lambda參數指定的表達式執行時間放大100萬倍,也就是執行100萬次這個表達式,然后統計時間總和,并且這一過程進行5遍,也就是說,repeat函數會執行lambda參數指定的表達式500萬次,最后得到5組時間值(單位是秒),然后用min函數挑出最小的值。
執行這段代碼,會輸出如圖1所示的結果:
很明顯,x | y的效率最高,兩個字典合并100萬次,只需要不到0.5秒,而最后一種方式最慢,需要2秒,所以最快的合并字典的方式比最慢的方式整整快了4倍。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的这样合并Python字典,可以让程序的运行效率提高4倍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python字典的排序方法,你用对了吗
- 下一篇: Python基础教程:如何打破while