不同於java那樣的強類型語言,python的參數定義和調用非常靈活,因為靈活所以也非常容易混淆,剛學python時覺得已經對這塊已經掌握的可以了就沒怎麼總結,今天看別人的代碼有個地方的參數傳遞看的不太明白,所以還是總結一下,參考的官方文檔,結合自己代碼測試,文檔地址:https://docs.python.org/zh-cn/3.6/tutorial/controlflow.html#more-on-defining-functions,往下拉就能看到參數部分。
python中的參數類型雖然多(位置參數/默認值參數/關鍵字參數/位置不定長參數/關鍵字不定長參數),但其實根本上只有兩種類型的參數(位置參數/關鍵字參數)。函數定義時對不同類型的參數順序沒有太嚴格的要求,只要保證默認值參數在位置參數之後就行,如果有關鍵字不定長參數的話,要把它放到最後面,比如下面的這幾種定義格式都是可以的,
第2種之所以正確是因為K-V形式的形參也可以在調用時以位置參數的形式賦值。
雖然幾種不同的定義格式都是允許的,但開發中應該選擇第一種。因為函數在調用時,要求實參中所有的位置參數都必須在關鍵字參數之前,會先拿實參中的位置參數從前到後依次為形參賦值,無論這個形參是位置參數形式還是K-V鍵值對形式,實參中多余的位置參數如果有不定長位置參數*args則會被作為一個元組收集起來,沒有的話就會報參數不匹配錯誤。然後再拿實參中的關鍵字參數匹配形參中同名的默認值參數,多余的關鍵字參數如果有不定長關鍵字參數**kwargs則作為一個字典被收集起來,否則報參數不匹配錯誤。根據這個參數匹配過程,在函數定義時也應該讓位置參數在前,關鍵字參數在後。至於兩個不定長參數*args、**kwargs只是用來收集多余的參數,在傳值時非必須,所以分別跟在位置參數和關鍵字參數的後面就可以了。
上面說這麼多只需記住一點,函數定義時的參數順序:def fun(a, *args, b=1, **kwargs)
,參數的類型可以沒這麼多,但類型之間的相對順序要保持相同。
1.默認值參數只會在函數初始化時加載一次,這條規則在默認值為可變對象(列表、字典以及大多數類實例)時很重要。比如,下面函數每次調用時的默認列表L一直是函數第一次被調用時的默認列表L:
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
輸出:
[1]
[1, 2]
[1, 2, 3]
2.*args和**kwargs真正的參數名是args與kwargs,不帶*號,參數名也可以自定義,只不過為了規范才用args與kwargs,方便理解。args與kwargs的類型分別為元組和字典,所以元組和字典有的屬性或方法它們也都可以使用。二者在收集多余的參數值時的優先級低於位置參數賦值與關鍵字參數賦值,也就是收集經位置參數賦值和關鍵字參數賦值後多余的參數。
3.定義時形參的格式與調用時實參的格式不要求必須一樣,也就是形參為位置參數實參也可以以關鍵字參數的形式傳值,形參為關鍵字參數實參也可以以位置參數的形式傳值。