I was going trough some code, and I came across the following function:
def foo(self, arg1=1, *, arg2=2):
pass
I was surprised to see keyword arguments on the left side of the *
, the positional arguments. I notice then that I can call foo
in both of the following ways:
>>> foo(1)
>>> foo(arg1=1)
I think I would be expecting the second call to fail as I am calling foo
using a named argument by providing the keyword arg1
.
With that said, am I using positional arguments in both scenarios, or is the second call to foo
a named argument?
The best sentence that I found that best describes this is:
"The trick here is to realize that a “keyword argument” is a concept of the call site, not the declaration. But a “keyword only argument” is a concept of the declaration, not the call site."
Below is a concise explanation copied from here in case the link dies at some point.
def bar(a, # <- this parameter is a normal python parameter
b=1, # <- this is a parameter with a default value
*, # <- all parameters after this are keyword only
c=2, # <- keyword only argument with default value
d): # <- keyword only argument without default value
pass
The arg1
argument is allowed to be called as either a positional argument, or a keyword argument.
As of Python 3.8, it is possible to specify some arguments as positional only. See PEP 570. Prior to 3.8, this isn't possible unless you write a python C extension.
The 3.8 syntax looks like this (directly from the PEP):
def name(positional_only_parameters, /, positional_or_keyword_parameters,
*, keyword_only_parameters): ...
...prior to 3.8, the only legal syntax is this:
def name(positional_or_keyword_parameters, *, keyword_only_parameters): ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With