本文轉(zhuǎn)載自:http://www.pythoner.com/13.html
Python中將兩個(gè)字典進(jìn)行合并操作怪瓶,是一個(gè)比較常見(jiàn)的問(wèn)題萧落。本文將介紹幾種實(shí)現(xiàn)兩個(gè)字典合并的方案,并對(duì)其進(jìn)行比較洗贰。
對(duì)于這個(gè)問(wèn)題找岖,比較直觀的想法是將兩個(gè)字典做相加操作,賦值給結(jié)果字典敛滋,其代碼為:
方法一:
1
dictMerged1
dict
( dict1.items()
dict2.items() )
然而许布,該方法合并時(shí)所用時(shí)間較長(zhǎng),效率更高的代碼為:
方法二:
1
dictMerged2
dict
( dict1,
dict2 )
這種方法使用的是dict()
工廠方法(Python2.2以上版本)绎晃。如果輸入?yún)?shù)是另一個(gè)字典(此處為dict1)蜜唾,則調(diào)用該工廠方法時(shí)會(huì)從dict1中復(fù)制內(nèi)容生成新的字典。該工廠方法從Python2.3版本開始庶艾,允許接受字典或關(guān)鍵字參數(shù)字典進(jìn)行調(diào)用袁余。但應(yīng)當(dāng)注意,對(duì)于這種調(diào)用方式咱揍,dict()
最多只接受一個(gè)參數(shù)(或者說(shuō)是一組name=value
的可變長(zhǎng)參數(shù))颖榜,而不會(huì)再接受另一個(gè)字典。因此直觀上的簡(jiǎn)單使用dict1與dict2兩個(gè)參數(shù)的方法會(huì)提示如下錯(cuò)誤:
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的朋友應(yīng)當(dāng)注意朱转,在這里的意思并不代表指針蟹地,這是Python中可變長(zhǎng)函數(shù)參數(shù)的寫法(關(guān)于可變長(zhǎng)函數(shù)參數(shù)的相關(guān)知識(shí)見(jiàn)下文)。在這里藤为,的意思是基于字典的可變長(zhǎng)函數(shù)參數(shù)怪与。*
方法2執(zhí)行的是如同下面方法3中的代碼,即先將dict1拷貝給dictMerged缅疟,在執(zhí)行update()
操作:
1
2
dictMerged3
dict1.copy()
dictMerged3.update( dict2 )
對(duì)于第一步的復(fù)制操作而言分别,這種使用內(nèi)建方法copy()
的復(fù)制方式,和方法2中的復(fù)制結(jié)果是一樣的存淫,但根據(jù)《Core Python Programming (2nd edition)》一書中7.3.2節(jié)所述耘斩,從已存在字典中生成新字典的方式dictNew = dict( dictOld )
較內(nèi)建方法dictNew = dictOld.copy()
會(huì)慢一些,因此書中推薦使用copy()
方法桅咆。
因此雀鹃,從這幾種方式看來(lái)匾二,方法3的效率最高鞋邑,并且代碼也比較易讀低剔。
Python可變長(zhǎng)度的函數(shù)參數(shù)
在編程的過(guò)程中,我們可能會(huì)遇到函數(shù)參數(shù)個(gè)數(shù)不固定的情況籍茧。這時(shí)就需要使用可變長(zhǎng)度的函數(shù)參數(shù)來(lái)實(shí)現(xiàn)我們的功能版述。在Python中,有兩種變長(zhǎng)參數(shù)寞冯,分別是元組(非關(guān)鍵字參數(shù))和字典(關(guān)鍵字參數(shù))渴析。其調(diào)用方式是:func( *tuple_grp_nonkw_args, *dict_grp_kw_args )
,下面將詳細(xì)介紹這兩種變長(zhǎng)參數(shù)吮龄。
1.元組變長(zhǎng)參數(shù)
當(dāng)函數(shù)調(diào)用中包括一個(gè)元組變長(zhǎng)參數(shù)tuple_grp_nonkw_args時(shí)俭茧,除去前面固定位置參數(shù)和關(guān)鍵字參數(shù)的其余參數(shù)將按順序插入一個(gè)元組進(jìn)行訪問(wèn),這和C語(yǔ)言中的varargs的功能相同漓帚。
假設(shè)有這樣一個(gè)函數(shù)(其中母债,positional_arg是位置固定的標(biāo)準(zhǔn)調(diào)用參數(shù),keyword_arg是關(guān)鍵字參數(shù)):
示例:
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
我們使用一些示例來(lái)了解它是怎么工作的:
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.字典變長(zhǎng)參數(shù)
既然Python中允許關(guān)鍵字參數(shù)胰默,那么也應(yīng)該有一種方式實(shí)現(xiàn)關(guān)鍵字的變長(zhǎng)參數(shù),這就是字典變長(zhǎng)參數(shù)漓踢。
字典變長(zhǎng)參數(shù)中牵署,額外的關(guān)鍵字參數(shù)被放入了一個(gè)字典進(jìn)行使用。字典中喧半,鍵為參數(shù)名奴迅,值為相應(yīng)的參數(shù)值。其表示方式是放在函數(shù)參數(shù)最后的開頭的參數(shù),如dict_grp_kw_args取具。(需要注意的是脖隶,**被重載以不與冪運(yùn)算混淆。)
以下是一個(gè)字典變長(zhǎng)參數(shù)的示例函數(shù):
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] ) )
下面是一段演示結(jié)果:
1
2
3
4
foo(
1
,
2
, a
=
"b"
)
positional arg:
1
keyword_arg:
2
dict_arg: a
b
3.注意
函數(shù)調(diào)用的完整表達(dá)形式為:func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )
在使用的過(guò)程中暇检,所有參數(shù)都是可選的产阱,但應(yīng)當(dāng)注意的是:上面四種參數(shù)的位置是不可調(diào)換的!
4.擴(kuò)展:C語(yǔ)言中的變長(zhǎng)參數(shù)
作為一個(gè)學(xué)藝不精的人块仆,之前一直不知道C語(yǔ)言中也是有可變參數(shù)的构蹬,直到在《Pointers on C》(中譯名:《C和指針》,人民郵電出版社)中看到相關(guān)內(nèi)容(7.6節(jié))悔据。
4.1 stdarg宏
在C語(yǔ)言中庄敛,可變參數(shù)是通過(guò)stdarg宏來(lái)實(shí)現(xiàn)的,它是標(biāo)準(zhǔn)庫(kù)的一部分科汗。這個(gè)頭文件聲明了一個(gè)類型va_list
和三個(gè)宏va_start
藻烤、va_arg
、va_end
头滔。我們可以聲明一個(gè)類型為va_list的變量怖亭,與三個(gè)宏配合使用,訪問(wèn)參數(shù)的值拙毫。
下面是一個(gè)計(jì)算多個(gè)數(shù)值平均值的示例函數(shù):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//下面是一個(gè)計(jì)算多個(gè)數(shù)值平均值的示例函數(shù):
include <stdarg.h>
float
avg(
int
n, ... ) {
va_list
var_arg;
float
sum = 0;
// 準(zhǔn)備訪問(wèn)變長(zhǎng)參數(shù)
va_start
( var_arg, n );
// 添加取自變長(zhǎng)參數(shù)列表的值
for
( i = 0; i < n; i += 1) {
sum +=
va_arg
( var_arg,
int
);
}
// 完成處理變長(zhǎng)參數(shù)
va_end
( var_arg);
return
sum / n;
}
其中依许,函數(shù)參數(shù)中的...
作為參數(shù)占位符,代表數(shù)量和類型不可知的一些參數(shù)缀蹄。
函數(shù)中聲明了一個(gè)va_list類型的變量var_arg用于訪問(wèn)參數(shù)列表的不確定部分峭跳。這個(gè)變量通過(guò)調(diào)用va_start進(jìn)行初始化,其中缺前,第一個(gè)參數(shù)是va_list變量的名字蛀醉,第二個(gè)參數(shù)是占位符前最后一個(gè)有名字的參數(shù)。初始化過(guò)程將var_arg變量指向可變參數(shù)中的第一個(gè)參數(shù)衅码。
va_list的使用中拯刁,包括兩個(gè)參數(shù),第一個(gè)參數(shù)是va_list變量逝段,第二個(gè)參數(shù)是下一個(gè)參數(shù)的類型垛玻。本例中假設(shè)輸入數(shù)據(jù)均為整型,因此均設(shè)置為int奶躯,而在一些情況下帚桩,下一個(gè)參數(shù)的類型會(huì)由之前的參數(shù)來(lái)決定。
最后嘹黔,調(diào)用va_end結(jié)束變長(zhǎng)參數(shù)的訪問(wèn)账嚎。
4.2 限制與注意事項(xiàng)
可變參數(shù)是從頭到尾進(jìn)行訪問(wèn)的,即可以在訪問(wèn)了數(shù)個(gè)參數(shù)之后結(jié)束,但不可以一開始就訪問(wèn)中間的參數(shù)郭蕉。
另外疼邀,由于可變參數(shù)部分沒(méi)有原型,因此作為可變參數(shù)傳遞給函數(shù)的值都做了缺省的函數(shù)類型提升召锈。
從va_start的調(diào)用可以看出旁振,如果使用可變參數(shù)必須有至少一個(gè)確定的參數(shù),否則無(wú)法使用va_start烟勋。
對(duì)于這些宏规求,有兩個(gè)基本限制:其一,無(wú)法判斷實(shí)際存在的參數(shù)數(shù)量卵惦;其二阻肿,不能判斷參數(shù)類型。
還需要注意的是沮尿,一旦在使用中寫錯(cuò)下一個(gè)參數(shù)的類型丛塌,后果可能不堪設(shè)想。