Using default arguments before positional arguments

I am studying the use of positional arguments in python, and also trying to see how they work when mixed 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 result:

 ae= 1 args = (2, [10, 20]) 

As you can see, a is considered the value passed to ae , and b , as well as c are considered positional arguments.

So now I'm trying to assign 10 to ae when calling withPositionalArgs :

 withPositionalArgs(ae=10,b,c) 

But I can’t do it. I get an error message:

 SyntaxError: non-keyword arg after keyword arg 

My question is:

Am I right? Does it have a valid default argument or good practice to use before positional arguments in python functions?

+8
python
source share
3 answers

In Python2, you are not allowed to put arguments that have a default value before positional arguments.

Positional arguments must be first, then arguments with default values ​​(or when calling a function, keyword arguments), then *args , and then **kwargs .

This order is required for both function definitions and function calls.

In Python3, the order has been weakened. (For example, *args may appear before a keyword argument in a function definition.) See PEP3102 .

+9
source share

I think we should make a distinction between default values ​​and passing to arbitrary argument / key-value pairs. The behavior without default values ​​is the same:

 def f(ae,*args, **kwargs): print 'ae = ', ae print 'args = ', args print 'kwargs = ', kwargs 

The way we wrote this means that the first argument is passed to f in the args tuple, i.e. f(1,2,3,a=1,b=2) (the sequence goes into 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 will throw a TypeError: f() got multiple values for keyword argument 'ae' , since the value ae tries to be changed twice.

.

One way: only install ae , if it is explicitly set, we can (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 the best practice ...

+2
source share

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) 
+1
source share

All Articles