Reputation: 781
I've been studying *args
and **kwargs
in python recently and I've come across that in python 3 one can use bare *
as in the example from the title to indicate that no positional arguments are allowed after it.
The problem is that I don't see how it matches the formal definition or 'argument list' in reference. There is a following definition of argument list:
argument_list ::= positional_arguments ["," keyword_arguments]
["," "*" expression] ["," keyword_arguments]
["," "**" expression]
| keyword_arguments ["," "*" expression]
["," keyword_arguments] ["," "**" expression]
| "*" expression ["," keyword_arguments] ["," "**" expression]
| "**" expression
The only way I see it to be valid is for expression
to be empty, but I couldn't see how it can happen.
In case we assume that expression
can be empty then the following definitions should be valid:
def foo(*)
def bar(*,**kwargs)
Those definitions don't make sense since *
requires keyword arguments after it.
So I would appreciate any clarifications on the subject. What do I miss? Or is the above BNF not quite correct?
Upvotes: 1
Views: 92
Reputation:
The part of the grammar you're looking at describes function calls. And a bare *
is indeed invalid in a function call.
The function definition grammar is in another part of the language reference. These productions are relevant:
parameter_list ::= (defparameter ",")*
( "*" [parameter] ("," defparameter)* ["," "**" parameter]
| "**" parameter
| defparameter [","] )
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
Note that here, parameter
s and defparameters
are optional after after the *
.
The error that complains about def f(*)
and def f(*, **kwds)
does not come from the grammar. It's legal as far as the grammar is concerned, and is parsed successfully. Only during AST generation this is detected and flagged as error. This isn't the only syntactical constraint that isn't handled in the grammar.
Upvotes: 4