*args 和 **kwargs 的區別
轉自:
https://www.cnblogs.com/lidaxian/p/7767364.html
寫得非常清楚,可以理解透徹.
1. 通過一個函式呼叫來理解’*’的作用
它拆開數列’l’的數值作為位置引數,並吧這些位置引數傳給函式’fun’來呼叫。
因此拆數列、傳位置引數意味著fun(*l)與fun(1,2,3)是等效的,因為l = [1,2,3]。
2. 通過一個函式的定義來理解’*args’的含義
它接收元組作為位置引數,而非是常見的引數列表。在這裡,”args”是個元組。在我們解釋中不要擔心”常見的引數”這部分的理解,這個會在接下來的例子中逐漸明瞭。在上個例子中,呼叫函式列印”args”時,他會列印元組中包含的所有數值。
我們重新定義函式,”*args”與”常規引數列表”混合使用
def fun(a, *args): print("a is ", a) print("args is ", args)
fun(11,12,34,43)
很容易看到,’a’打印出為11,即第一個位置引數。’a’之後只一個引數’*args’.因此,’args’接收除常規引數之外的位置引數作為元組。因此元組args作為元組接收12,34和43。
fun(91)
在這裡,我們傳的唯一一個引數分配給了常規引數’a’.因此,’args’接收到一個空元組。
‘args’既然是元組,我們就可以遍歷它。
現在我們考慮使用所有能得到的引數的場景。我們需要使用兩個函式,第一個函式帶有任意個引數,並通過另外一個函式計算除第一引數的其他引數之和。奇怪的用例,但我們只需回顧我們目前所做的。我們的目的就是在一個函式中獲取可變引數,並把這些引數餐給另一個函式。
def calculate_sum(*args): return sum(args) def ignore_first_calculate_sum(a,*iargs): required_sum = calculate_sum(*iargs) print("sum is ", required_sum)
我們可以傳任意個引數給這個函式。第一個引數被常規引數’a’接收,其他引數被’iargs’作為元組接收。正如我們考慮的案例,計算除第一個引數之外的其他引數的和。因此,我們用’a’接收第一個引數,’iargs’是包含其他引數的元組。我們用到函式’calculate_sum’,但’calculate_sum’需要多個位置引數作為元組傳給’args’。所以在函式’ignore_first_calculate_sum’需要拆元組’iargs’,然後將元素作為位置引數傳給’calculate_sum’.注意,用’*’拆元組。
3. 通過一個函式的呼叫來理解’**’的作用
使用”**”呼叫函式,這種方式我們需要一個字典.注意:在函式呼叫中使用”*”,我們需要元組;在函式呼叫中使用”**”,我們需要一個字典
def fun(a, b, c): return a, b, c d={'b':5, 'c':7} fun(1, **d)
它unpack字典,並將字典中的資料項作為鍵值引數傳給函式。因此,”fun(1, **d)”的寫法與”fun(1, b=5, c=7)”等效.
4. 通過一個函式的定義來解’**kwargs’的含義
def fun(a, **kwargs): print(a, kwargs)
此函式只用一個位置引數,因為常規引數列表中只有一個變數’a’.但是通過”**kwargs”,可以傳多個鍵值引數。
fun(1, b=4, c=5)
用”**kwargs”定義函式,kwargs接收除常規引數列表職位的鍵值引數字典。在這裡’kwargs’是個字典。
def fun(a, **kwargs): print("a is ", a) print("We expect kwargs 'b' and 'c' in this function") print("b is ", kwargs['b']) print("c is ", kwargs['c']) fun(1, b=3, c=5) fun(1, b=3, d=5)
上面的呼叫,位置引數’a’和鍵值引數’b’都打印出來了。傳入的其他鍵值引數是’d’,函式需要鍵值引數’c’,並從字典’kwargs’獲取。但沒有傳入鍵值’c’,引發KeyError.如果傳入了鍵值’c’就不會引發這個錯誤
fun(1, b=3, d=5, c=9)
由於’**kwargs’在函式引數列表中,我們可以傳任意個鍵值引數。上面的呼叫傳入了”d”,但函式並沒用到。
fun(1, {'b':2, 'c':34}) fun(1, **{'b':2, 'c':34})
儘管’kwargs’接收鍵值引數作為一個字典,但你不能傳一個字典作為位置引數給’kwargs’.你可以像上面那樣呼叫:
在一個字典前使用”**”可以unpack字典,傳字典中的資料項作為鍵值引數。