2014-08-27 74 views
1

我對函數調用中的函數頭和參數規則中的參數規則有些混淆。函數調用和*表達式

這裏是我的困惑點:

根據文檔:

如果語法*表達出現在函數調用,表達式必須可迭代。來自這個迭代器的元素被視爲它們是附加的位置參數;如果存在位置參數x1,...,xN,並且表達式計算爲序列y1,...,yM,則這相當於具有M + N個位置參數x1,...,xN,y1,...的調用。 ..,yM。

因此,如果有這樣的功能:

def func(a, *b): .... 

爲什麼我不能做這樣的事情:

func(1, *[2, 3], *[4, 5]) 

這不是等同於X1,... ,xN,y1,...,yN,w1,...,wN 爲什麼不能工作?

+2

而你引用的非常相同的文檔包括語法語法。官方語法只允許**一個**'*表達式'。 – 2014-08-27 10:32:57

回答

4

首先,不要被那*args既可以在函數聲明和函數調用中使用的事實混淆。雖然兩者關係鬆散,但它們並不是一回事。您可以調用一個函數foo(*args)而不用聲明可變數量的參數,並且用def foo(*args)定義的函數不需要用解壓縮的可迭代函數調用。

您看到的真正問題是在函數調用中只允許一個*args解包。這就是Python的語法是如何指定的。儘管如此,這可能會在未來發生變化,因爲PEP 448尋求推廣unpacking語法,因此可以在更多情況下使用它。如果PEP得到批准並實施,函數調用如foo(*args, *args2)將成爲合法。

0

因爲語法不允許它。

您可以使用以下代替來達到同樣的效果:

func(1, *([2, 3] + [4, 5])) 
+2

在函數被調用之前,惰性迭代器將被完全評估,所以你不會獲得任何東西。 – jonrsharpe 2014-08-27 10:34:50

+0

@jonrsharpe你是對的;我糾正了(編輯答案)。 – 2014-08-27 10:39:09

3

首先,它並沒有什麼功能簽名是調用語法函數定義是碰巧使用*來表示相關事物的兩個單獨的概念。 f()的定義在這裏並不重要。

它是在Calls expressions documentation不允許多個*expression*部件所限定的非常語法:

argument_list  ::= positional_arguments ["," keyword_arguments] 
          ["," "*" expression] ["," keyword_arguments] 
          ["," "**" expression] 
          | keyword_arguments ["," "*" expression] 
          ["," keyword_arguments] ["," "**" expression] 
          | "*" expression ["," keyword_arguments] ["," "**" expression] 
          | "**" expression 

每個|是一種替代一部分,每個[...]是可選的。這些都不允許*expression出現多次。

請注意,有在 Python 2 rendering of the documentation一個bug,其中

| "*" expression ["," keyword_arguments] ["," "**" expression] 

已替換不正確的

| "*" expression ["," "*" expression] ["," "**" expression] 

issue #22288(文檔有been fixed)。

未來的Python版本可能放鬆此限制。見PEP 448 - Additional Unpacking Generalizations;這隻適用於Python的最新版本,即Python 3.5。

+0

爲什麼只允許一個'*'而不是更多?我不知道,可讀性,可用性... – zer0uno 2014-08-27 10:41:53

+2

@antox:更簡單的初始實現,更可能。 PEP試圖集中討論可以擴展到的內容。 Guido似乎積極傾向於此(請參閱他對[相關Python問題]的評論(http://bugs.python.org/issue2292))。 – 2014-08-27 10:45:40