Ответ 1
Посмотрите на спецификацию языка:
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
. Я согласен, что это хромает.