为什么使用* args语法的参数列表中的尾随逗号是SyntaxError?
为什么你不能在Python中使用尾随逗号和*args
? 换句话说,这是有效的
>>> f(1, 2, b=4,)
但是这不是
>>> f(*(1, 2), b=4,) File "<stdin>", line 1 f(*(1, 2), b=4,) ^ SyntaxError: invalid syntax
Python 2和Python 3都是这种情况。
我们来看看语言规范 :
call ::= primary "(" [argument_list [","] | expression genexpr_for] ")" argument_list ::= positional_arguments ["," keyword_arguments] ["," "*" expression] ["," keyword_arguments] ["," "**" expression] | keyword_arguments ["," "*" expression] ["," "**" expression] | "*" expression ["," "*" expression] ["," "**" expression] | "**" expression positional_arguments ::= expression ("," expression)* keyword_arguments ::= keyword_item ("," keyword_item)* keyword_item ::= identifier "=" expression
让我们筛选我们关心的部分:
call ::= primary "(" [argument_list [","]] ")" argument_list ::= positional_arguments ["," keyword_arguments] ["," "*" expression] ["," keyword_arguments] ["," "**" expression] positional_arguments ::= expression ("," expression)* keyword_arguments ::= keyword_item ("," keyword_item)* keyword_item ::= identifier "=" expression
所以,看起来像在函数调用的任何参数后,我们被允许额外的,
。 所以这看起来像cpython实现中的一个错误。
类似于: f(1, *(2,3,4), )
应根据此语法工作,但不在CPython中。
在之前的回答中, Eric链接到CPython语法规范 ,其中包括上述语法的CPython实现。 这里是:
arglist: (argument ',')* ( argument [','] | '*' test (',' argument)* [',' '**' test] | '**' test )
请注意,这个语法不同于语言规范提出的语法。 我会考虑这个实现的错误。
请注意,CPython实现还有其他问题。 这也应该被支持: f(*(1,2,3), *(4,5,6))
奇怪的是,规范不允许f(*(1,2,3), *(4,5,6), *(7,8,9))
当我看到更多的时候,我认为这部分的规范需要一些修复。 这是允许的: f(x=1, *(2,3))
,但这不是: f(x=1, 2, 3)
。
对于原始问题也许会有所帮助,在CPython中,如果不使用*args
或**kwargs
function,则可以使用尾随逗号。 我同意这是跛脚。
在对9232号问题进行了一些讨论之后,Guido van Rossum 评论道 :
我在+1上添加这个。 我不相信这需要一个PEP。 定义中的尾随逗号在某些地方已经得到支持,所以我不会购买它捕捉错误的观点。 在暂停期间,我们可能太严格了。
随后, 由马克·迪金森(Mark Dickinson )做了一个补丁 。 所以现在已经在Python 3.6.0 alpha 1中修复了。