【轉載】Python中如何高效實現兩個字典合并,三種方法比較。

本文轉載自:http://www.pythoner.com/13.html
Python中將兩個字典進行合并操作,是一個比較常見的問題。本文將介紹幾種實現兩個字典合并的方案,并對其進行比較。
對于這個問題,比較直觀的想法是將兩個字典做相加操作,賦值給結果字典,其代碼為:
方法一:
1

dictMerged1

dict
( dict1.items()

dict2.items() )

然而,該方法合并時所用時間較長,效率更高的代碼為:
方法二:
1

dictMerged2

dict
( dict1,

dict2 )

這種方法使用的是dict()
工廠方法(Python2.2以上版本)。如果輸入參數是另一個字典(此處為dict1),則調用該工廠方法時會從dict1中復制內容生成新的字典。該工廠方法從Python2.3版本開始,允許接受字典或關鍵字參數字典進行調用。但應當注意,對于這種調用方式,dict()
最多只接受一個參數(或者說是一組name=value
的可變長參數),而不會再接受另一個字典。因此直觀上的簡單使用dict1與dict2兩個參數的方法會提示如下錯誤:
1
2
3
4

dictMerged
=
dict
( dict1, dict2 )

Traceback (most recent call last):

File
"<stdin>"
, line
1
,
in
<module>

TypeError:
dict
expected at most
1
arguments, got
2

這也就是我們看到上面的方法2中使用的是dict2的原因。熟悉C的朋友應當注意,在這里的意思并不代表指針,這是Python中可變長函數參數的寫法(關于可變長函數參數的相關知識見下文)。在這里,的意思是基于字典的可變長函數參數。*
方法2執行的是如同下面方法3中的代碼,即先將dict1拷貝給dictMerged,在執行update()
操作:
1
2

dictMerged3

dict1.copy()

dictMerged3.update( dict2 )

對于第一步的復制操作而言,這種使用內建方法copy()
的復制方式,和方法2中的復制結果是一樣的,但根據《Core Python Programming (2nd edition)》一書中7.3.2節所述,從已存在字典中生成新字典的方式dictNew = dict( dictOld )
較內建方法dictNew = dictOld.copy()
會慢一些,因此書中推薦使用copy()
方法。
因此,從這幾種方式看來,方法3的效率最高,并且代碼也比較易讀。

Python可變長度的函數參數
在編程的過程中,我們可能會遇到函數參數個數不固定的情況。這時就需要使用可變長度的函數參數來實現我們的功能。在Python中,有兩種變長參數,分別是元組(非關鍵字參數)和字典(關鍵字參數)。其調用方式是:func( *tuple_grp_nonkw_args, *dict_grp_kw_args )
,下面將詳細介紹這兩種變長參數。
1.元組變長參數
當函數調用中包括一個元組變長參數
tuple_grp_nonkw_args時,除去前面固定位置參數和關鍵字參數的其余參數將按順序插入一個元組進行訪問,這和C語言中的varargs的功能相同。
假設有這樣一個函數(其中,positional_arg是位置固定的標準調用參數,keyword_arg是關鍵字參數):
示例:
1
2
3
4
5

def
foo( positional_arg, keyword_arg
=
'default'
,

tuple_arg ):

print
"positional arg: "
, positional_arg

print
"keyword_arg: "
, keyword_arg

for
each_additional_arg
in
tuple_arg:

print
"additional_arg: "
, each_additional_arg

我們使用一些示例來了解它是怎么工作的:

foo(
1
)

positional arg:
1

keyword_arg: default

foo(
1
,
2
)

positional arg:
1

keyword_arg:
2

foo(
1
,
2
,
3
)

positional arg:
1

keyword_arg:
2

additional_arg:
3


1
2
3
4
5
6
7
8
9
10
11

foo(
1
,
2
,
3
,
4
,
5
,
6
)

positional arg:
1

keyword_arg:
2

additional_arg:
3

additional_arg:
4

additional_arg:
5

additional_arg:
6

foo(
1
,
2
,(
3
,
4
,
5
,
6
))

positional arg:
1

keyword_arg:
2

additional_arg: (
3
,
4
,
5
,
6
)

2.字典變長參數
既然Python中允許關鍵字參數,那么也應該有一種方式實現關鍵字的變長參數,這就是字典變長參數。
字典變長參數中,額外的關鍵字參數被放入了一個字典進行使用。字典中,鍵為參數名,值為相應的參數值。其表示方式是放在函數參數最后的開頭的參數,如dict_grp_kw_args。(需要注意的是,**被重載以不與冪運算混淆。)
以下是一個字典變長參數的示例函數:
1
2
3
4
5

def
foo( positional_arg, keyword_arg
=
'default'
,

dict_arg ):

print
"positional arg: "
, positional_arg

print
"keyword_arg: "
, keyword_arg

for
each_dict_arg
in
dict_arg.keys():

print
"dict_arg: %s=>%s"
%
( each_dict_arg,
str
( dict_arg[each_dict_arg] ) )

下面是一段演示結果:
1
2
3
4

foo(
1
,
2
, a
=
"b"
)

positional arg:
1

keyword_arg:
2

dict_arg: a

b

3.注意
函數調用的完整表達形式為:func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )

在使用的過程中,所有參數都是可選的,但應當注意的是:上面四種參數的位置是不可調換的!
4.擴展:C語言中的變長參數
作為一個學藝不精的人,之前一直不知道C語言中也是有可變參數的,直到在《Pointers on C》(中譯名:《C和指針》,人民郵電出版社)中看到相關內容(7.6節)。
4.1 stdarg宏
在C語言中,可變參數是通過stdarg宏來實現的,它是標準庫的一部分。這個頭文件聲明了一個類型va_list
和三個宏va_start
、va_arg
、va_end
。我們可以聲明一個類型為va_list的變量,與三個宏配合使用,訪問參數的值。
下面是一個計算多個數值平均值的示例函數:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

//下面是一個計算多個數值平均值的示例函數:

include <stdarg.h>

float
avg(
int
n, ... ) {

va_list
var_arg;

float
sum = 0;

// 準備訪問變長參數

va_start
( var_arg, n );

// 添加取自變長參數列表的值

for
( i = 0; i < n; i += 1) {

sum +=
va_arg
( var_arg,
int
);

}

// 完成處理變長參數

va_end
( var_arg);

return
sum / n;

}

其中,函數參數中的...
作為參數占位符,代表數量和類型不可知的一些參數。
函數中聲明了一個va_list類型的變量var_arg用于訪問參數列表的不確定部分。這個變量通過調用va_start進行初始化,其中,第一個參數是va_list變量的名字,第二個參數是占位符前最后一個有名字的參數。初始化過程將var_arg變量指向可變參數中的第一個參數。
va_list的使用中,包括兩個參數,第一個參數是va_list變量,第二個參數是下一個參數的類型。本例中假設輸入數據均為整型,因此均設置為int,而在一些情況下,下一個參數的類型會由之前的參數來決定。
最后,調用va_end結束變長參數的訪問。
4.2 限制與注意事項
可變參數是從頭到尾進行訪問的,即可以在訪問了數個參數之后結束,但不可以一開始就訪問中間的參數。
另外,由于可變參數部分沒有原型,因此作為可變參數傳遞給函數的值都做了缺省的函數類型提升。
從va_start的調用可以看出,如果使用可變參數必須有至少一個確定的參數,否則無法使用va_start。
對于這些宏,有兩個基本限制:其一,無法判斷實際存在的參數數量;其二,不能判斷參數類型。
還需要注意的是,一旦在使用中寫錯下一個參數的類型,后果可能不堪設想。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容