2010-04-25 22 views
7

我在這裏錯過了什麼嗎?爲什麼不應該在「Broken」部分下的代碼工作?我正在使用Python 2.6。Python中奇怪的語法分析錯誤?

#!/usr/bin/env python 

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

#Working: Example #1: 

p={'c':3} 

func(1, 
    b=2, 
    c=3, 
    ) 

#Working: Example #2: 

func(1, 
    b=2, 
    **p) 

#Broken: Example #3: 

func(1, 
    b=2, 
    **p, 
    ) 
+2

當我在Python 2.6下嘗試此代碼時,第19行(第二個Working)出現語法錯誤。 – 2010-04-25 15:04:33

+0

謝謝,修正了例子#2中的小錯字。 – user213060 2010-04-25 15:07:59

+1

和(不重要):你爲什麼要這個逗號逗號(除了研究這種行爲)? – ChristopheD 2010-04-25 15:09:59

回答

9

這是從grammar的相關位:

arglist: (argument ',')* (argument [','] 
         |'*' test (',' argument)* [',' '**' test] 
         |'**' test) 

這裏的第一行允許把最後一個參數之後逗號沒有使用可變參數/ kwargs(這就是爲什麼你的第一個例子工程)時。但是,如果指定了kwargs參數,則不允許放置逗號,如第二行和第三行所示。

順便說一句,這裏是由文法所示一件有趣的事:

這些都是合法的:

f(a=1, b=2, c=3,) 
f(*v, a=1, b=2, c=3) 

但這不是:

f(*v, a=1, b=2, c=3,) 

這是有道理的不在**kwargs之後允許逗號,因爲它必須始終是最後一個參數。我不知道爲什麼語言設計師選擇不讓我的最後一個例子 - 也許是一個疏忽?

5

Python通常允許在逗號列表末尾附加逗號(在參數列表和容器文字中)。這樣做的主要目標是使代碼生成稍微簡單一些(不必特殊說明最後一項或雙特殊情況下的單例元組)。

在語法的定義中,**kwargs被單獨提取出來,沒有額外的可選逗號。就我所能想象的那樣,它永遠不會對代碼生成這樣的實踐有幫助(** kwargs將永遠是最後一件事,所以你不必特殊處理任何事情),所以我不知道爲什麼Python會支持它。