为什么不能*args
在 Python 中使用尾随逗号?换句话说,这有效
>>> 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 都是这种情况。
为什么不能*args
在 Python 中使用尾随逗号?换句话说,这有效
>>> 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
or**kwargs
功能,则可以使用尾随逗号。我同意这是蹩脚的。
在对issue 9232中的这个错误进行了一些讨论之后,Guido van Rossum评论道:
我在添加此内容时 +1。我不认为它需要 PEP。在某些地方已经支持定义中的尾随逗号,所以我不相信它会捕获错误的论点。在暂停期间,我们可能过于严格了。
随后,Mark Dickinson提交了一个补丁。所以这现在在 Python 3.6.0 alpha 1 中得到修复。