1. 程式人生 > >*args 和 **kwargs 的區別

*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字典,傳字典中的資料項作為鍵值引數。