69 votes

Pourquoi une virgule de fin est-elle une SyntaxError dans une liste d'arguments qui utilise la syntaxe *args ?

Pourquoi ne pouvez-vous pas utiliser une virgule de fin avec *args en Python ? En d'autres termes, cela fonctionne

>>> f(1, 2, b=4,)

Mais cela ne

>>> f(*(1, 2), b=4,)
  File "<stdin>", line 1
    f(*(1, 2), b=4,)
                   ^
SyntaxError: invalid syntax

C'est le cas avec Python 2 et Python 3.

100voto

sharth Points 25625

Regardons les spécification du langage :

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

Passons en revue les parties qui nous intéressent :

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

Donc, il semble qu'après tout argument d'un appel de fonction, nous avons le droit à un supplément. , . Cela ressemble donc à un bogue dans l'implémentation de cpython.

Quelque chose comme : f(1, *(2,3,4), ) devrait fonctionner selon cette grammaire, mais ne le fait pas en CPython.


Dans une réponse précédente, Eric lié à la Spécification de la grammaire CPython qui comprend l'implémentation CPython de la grammaire ci-dessus. Le voici ci-dessous :

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

Notez que cette grammaire est pas la même chose comme celle proposée par la spécification du langage. Je considérerais cela comme un bug d'implémentation.


Notez qu'il existe des problèmes supplémentaires avec l'implémentation de CPython. Ceci devrait également être pris en charge : f(*(1,2,3), *(4,5,6))

Bizarrement, la spécification ne permet pas f(*(1,2,3), *(4,5,6), *(7,8,9))

En regardant de plus près, Je pense que cette partie de la spécification doit être corrigée. C'est autorisé : f(x=1, *(2,3)) mais ce n'est pas le cas : f(x=1, 2, 3) .


Et pour répondre à la question initiale, en CPython, vous pouvez avoir une virgule de fin si vous n'utilisez pas l'attribut *args ou le **kwargs fonction. Je suis d'accord pour dire que c'est nul.

6voto

BioGeek Points 3724

Après quelques discussions concernant ce bogue dans numéro 9232 Guido van Rossum a commenté :

Je suis +1 pour l'ajouter. Je ne crois pas que cela nécessite un PEP. Une virgule de fin dans les définitions est déjà prise en charge à certains endroits, donc je ne crois pas à l'argument selon lequel cela permet de détecter des erreurs. Pendant le moratoire, nous étions peut-être trop stricts.

Par la suite, un patch de Mark Dickinson a été commise. Ce problème est donc maintenant corrigé dans Python 3.6.0 alpha 1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X