函數參數的匹配原則
位置:從左至右進行匹配
一般情況下,是通過位置進行匹配,把參數值傳遞給函數頭部的參數名稱,匹配順序為從左到右。
關鍵字參數:通過參數名進行匹配
調用者可以定義哪一個函數接收這個值,通過在調用的時候使用參數的變量名,使用name=value這種語法。
默認參數:為沒有傳入值的參數定義參數值
如果調用時傳入的值過於少的話,函數能夠為參數設定默認的參數值,使用name=value這種語法。
可變參數:接收任意多基於位置或關鍵字的參數
函數能夠使用特定的參數,它們是已字符*開頭,接收任意多的額外參數(這個特定常常叫做可變參數)
可變參數解包:傳遞任意多的基於位置或關鍵字的參數
調用者能夠再使用*語法去將參數集合打散,分成參數。這個“*”與在函數頭部的“*”恰恰相反:在函數頭部它意味着收集任意多的參數,而在調用者中意味着傳遞任意多的參數。
匹配語法
函數參數匹配表1
語法 | 位置 | 解釋 |
fun(value) | 調用者 | 常規參數:通過位置進行匹配 |
fun(name=value) | 調用者 | 關鍵字參數:通過位置進行匹配 |
fun(*sequence) | 調用者 | 以name傳遞所有的對象,並作為獨立的基於位置的參數 |
fun(**dict) | 調用者 | 以name成對的傳遞所有的關鍵字/值,並作為獨立的關鍵字參數 |
def fun(name) | 函數 | 常規參數: 通過位置或變量名進行匹配 |
def fun(name=value) | 函數 | 默認參數值,如果沒有在調用中傳遞的話 |
def fun(*name) | 函數 | 匹配並收集(在元組中)所有包含位置的參數 |
def fun(**name) | 函數 | 匹配並收集(在字典中)所有包含關鍵字的參數 |
這些特殊的匹配模式分解到如下的函數調用和定義中:
- 在函數調用中(在表中前4行),簡單的通過變量名位置進行匹配,但是使用name=value的形式告訴python依照變量名進行匹配,這些叫做關鍵字參數。在調用中使用*sequence或者**dict允許我們在一個序列或字典中相應地封裝任意多的位置相關或者關鍵字對象,並且在將它們傳遞給函數的時候,將它們解包為分開的、單個的參數。
- 在函數頭部,一個簡單的變量名是通過位置或者變量名進行匹配的(取決於調用者是如何傳遞參數給它的),但是name=value的形式定義了默認的參數值。*name的形式收集了任意的額外不匹配的參數到元組中,並且**name的形式將會收集額外的關鍵字參數到字典中
示例:
##調用關系中的*和**參數,匹配表1的3、4行 #*參數 >>> def fun2(a,b,c,d):print a,b,c,d ... >>> fun2(1,2,*(3,4)) 1 2 3 4 #**參數 >>> def abc(a=1,b=2,c=3): ... print a,b,c ... >>> abc({'a':10,'b':20,'c':30}) {'a': 10, 'c': 30, 'b': 20} 2 3 >>> abc(**{'a':10,'b':20,'c':30}) 10 20 30
細節
如果決定使用並混合特定的參數匹配模型,python將會遵循下面的原則:
- 在函數調用中,參數必須以此順序出現:任何位置參數,后面跟着任何關鍵字參數(name=value)和*sequence形式的組合,后面跟着**dict形式。
- 在函數(定義)頭部,參數必須以此順序出現:任何一般參數(name),后面緊跟着默認參數(name=value),如果有的話,后面是*name的形式, 后面跟着**name形式。
示例:
>>> def func4(a,b,c=1,*args,**kwargs):print a,b,c,args,kwargs ...>>> func4(1,2,*(3,4),**{'c':11,'d':22}) Traceback (most recent call last):#見解釋2 File "<stdin>", line 1, in <module> TypeError: func4() got multiple values for keyword argument 'c' >>> func4(1,2,*(3,4),**{'aa':11,'d':22}) 1 2 3 (4,) {'aa': 11, 'd': 22}#見解釋1
解釋:
1,在函數調用中*args中的值會優先匹配位置參數,剩下的才會放到args變量中;
2,調用時,**kwargs中不能包含已經賦值的位置參數的名稱,除非此位置參數未賦值;
在調用和函數頭部中,如果出現**kwargs的話,都必須出現在最后。如果你使用任何其他的順序混合了參數,你將會得到一個語法錯誤,因為其他順序的混合會產生歧義。
python內部是使用一下步驟來在賦值前進行參數匹配的:
1,通過位置分配非關鍵字參數。
2,通過匹配變量名分配關鍵字參數。
3,其他額外的非關鍵字參數分配到*args元組中。
4,其他額外的關鍵字參數分配到**kwargs字典中。
5,用默認值分配給在頭部未得到分配的參數。
示例:
##綜合調用 >>> def fun3(a,b,*args,**kwargs): ... print a,b,args,kwargs ... >>> fun3(3,4,5,6,7,8,x=10,y=20) 3 4 (5, 6, 7, 8) {'y': 20, 'x': 10}
參考:《python學習手冊》(第四版),修改了部分語句和錯誤,並添加示例