I am learning to use positional arguments in python and also trying to see how they work when mixed up with default arguments:-
def withPositionalArgs(ae=9,*args):
print 'ae= ', ae
print 'args = ', args
a=1
b=2
c=[10,20]
withPositionalArgs(a,b,c)
This gives me the output:
ae= 1
args = (2, [10, 20])
As you can see, a
is considered to be a value passed for ae
, and b
as well as c
are considered to be the positional arguments.
So, I am now trying to assign 10
for ae
while calling withPositionalArgs
:
withPositionalArgs(ae=10,b,c)
But, I can not do it. I get the error:
SyntaxError: non-keyword arg after keyword arg
My question is:
Am I doing correctly? Is having default argument allowed or a good practice to use before positional arguments in python functions?
In Python2, you are not allowed to put arguments which have a default value before positional arguments.
The positional arguments must come first, then the arguments with default values (or, when calling the function, the keyword arguments), then *args
, and then **kwargs
.
This order is required for both the function definition and for function calls.
In Python3, the order has been relaxed. (For example, *args
can come before a keyword argument in the function definition.) See PEP3102.
I think we should make the distinction of default values vs. passing in arbitrary arguments/key-value pairs. The behaviour without default values is the same:
def f(ae,*args, **kwargs):
print 'ae = ', ae
print 'args = ', args
print 'kwargs = ', kwargs
The way we have written this means that the first argument passed into f
in the tuple args
, that is f(1,2,3,a=1,b=2)
(the sequence goes explicit arguments, *args, **kwargs.) Here: ae = 1, args = (2,3), kwargs = {'a': 1, 'b': 2}
.
If we try to pass in f(1,2,3,a=1,ae=3)
we are thrown a TypeError: f() got multiple values for keyword argument 'ae'
, since the value of ae
is attempted to be changed twice.
.
One way around this is to only set ae
when it is explicitly prescribed, we could (after the def line):
def g(*args, **kwargs):
kwargs, kwargs_temp = {"ae": 9}, kwargs
kwargs.update(kwargs_temp) #merge kwargs into default dictionary
and this time g(1,2,3,a=1,ae=3)
sets args=(1,2,3), kwargs={a=1,ae=3}
.
However, I suspect this is not best practice...
Python3 has relaxed ordering.
Now you can do something like:
def withPositionalArgs(*args, ae=9):
print('ae=', ae)
print('args =', args)
a=1
b=2
c=[10, 20]
withPositionalArgs(a, b, c, ae=7)
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