0

As I understand it, the python language reference is written in extended BNF format. While looking at the documentation for function definitions I noticed that the spec doesn't seem to support the usage of trailing *args or **kwargs parameters.

parameter_list ::=  (defparameter ",")*
                    | "*" [parameter] ("," defparameter)* ["," " ** " parameter]
                    | "**" parameter
                    | defparameter [","] )

See: https://docs.python.org/3/reference/compound_stmts.html#grammar-token-defparameter

And yet when I do a function def like so:

def func(arg1, *args, **args):

The python interpreter considers it to be legal.

What am I missing? From the spec it appears that you must have the * at the beginning of the function definition before any other parameters.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
limik
  • 39
  • 1
  • 3
  • 2
    I don't understand your question. It says `"*" [parameter]` and `"**" parameter` right there. – BrenBarn Mar 05 '15 at 19:54
  • right but doesn't the parameter_list spec mean that a parameter list is either a list of parameters OR a * followed by a list of parameters, OR ** parameter, OR a single parameter. In which case there is no where that a parameter list may be parameters followed by *identifier or parameters followed by **kwargs etc. – limik Mar 05 '15 at 19:57
  • There's a note there that says (about something different) "... this is a syntactic restriction that is not expressed by the grammar." It would seem that in your case this is a syntactic flexibility/allowance that s not expressed by the grammar. – jedwards Mar 05 '15 at 20:08

1 Answers1

1

It appears to be a documentation bug for which an issue has been raised.

I think the definitions in the documentation are slightly simplified in order to be easier to read. The "real" definition is given in the full grammar specification:

funcdef: 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
       ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]]
     |  '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
tfpdef: NAME [':' test]

This is more difficult to read but appears to correctly allow varargs with or without ordinary arguments.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384