为什么在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都是这种情况。
最佳答案
让我们看看language specification:
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 grammar specification,其中包括上述语法的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
功能,则可以使用逗号结尾。我同意这很la脚。