2017-09-06 17 views
2

我一直在試圖理解Python爲函數參數賦值時所遵循的算法,它只是非常混亂。我想更好地理解算法,以便我可以真正知道將什麼值分配給哪些參數以及何時分配。有位置參數,關鍵字參數,* args,* kwargs和僅關鍵字參數。這些全部如何分配以及按什麼順序分配?將值分配給函數參數時,Python遵循的過程是什麼?

看看下面的代碼片段爲一個具體的例子:

def func(a, b, c): 
    print(a, b, c) 

如果我撥打以下格式此功能,它會正常運行:如果我運行它

func(c=3, *(1, 2)) # prints 1 2 3 

然而使用此,它提供了SyntaxError

func(c=3, 1, 2) 

如何是次的兩種形式電話不同?在第一次調用中,元組被解包成單獨的參數。與轉換成第二種形式不一樣嗎?如果這就是發生了什麼,那麼第二種形式也應該起作用,但事實並非如此。

那麼這裏究竟發生了什麼?

回答

1

它沒有什麼特別之處:它就是Python的工作原理。

Python禁止在命名參數後傳遞位置參數。就像你不能用之後的可選參數或之後的之後的關鍵字參數定義一個函數。然而,在調用一個函數時,更多的是在命名參數前使用位置參數,而對於函數定義來說,它實際上是一個「消除模糊性」的問題。但它的工作方式肯定有一些對稱性。

你可以繞過這是你通過拆包觀察,但它是有代價的:這是一個有點慢,因爲額外的工作:

def func(a, b, c): 
    pass 

%timeit func(c=3, *(1, 2)) 
# 810 ns ± 16.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 
%timeit func(1, 2, c=3) 
# 383 ns ± 1.47 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 

這實際上是非常重要的是要記住:如果您嘗試與您付費的Pythons語言進行對抗。


如果你有興趣,它基本上作品就像如果你的函數只有*args**kwargs作爲參數。它收集*args中的所有位置參數和**kwargs中的所有命名參數,然後嘗試將它們「綁定」到實際的函數參數。

+0

但*爲什麼*不是有效的語法?它可以只分配關鍵字參數,然後將其餘的值分配給任何空白參數,就像我在示例中爲第二個呼叫類型所做的那樣。 –

+0

因爲這就是Pythons語言的語法。解包參數與傳遞位置參數不同。 – MSeifert

+0

@AsadMoosvi我更新了答案。我認爲原來的答案錯過了這一點。感謝您的評論 :) – MSeifert

0

在Python中,當使用參數調用函數時,它將按照在函數定義中定義的順序將這些值分配給參數。

對於防爆:

def func(a, b, c): 
    print(a, b, c) 
func(a=3, *(1, 2)) 

這將導致

TypeError: func() got multiple values for keyword argument 'a'

OR

def func(a, b, c): 
    print(a, b, c) 
func(b=3, *(1, 2)) 

這將導致

TypeError: func() got multiple values for keyword argument 'b'

因此,在這種情況下,變量c被明確分配,其餘參數從變長參數列表中分配。

來到這個問題的第二部分,Python允許你只後所有的值都passed.Following代碼將正常工作,明確分配的數據參數

def func(a, b, c): 
     print(a, b, c) 
    func(3, 1,c=2)) 

但不func(3,b=1,2) or func(a=3,1,2)

你可以在這裏找到更多的信息What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

相關問題