Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In python, can you pass variadic arguments after named parameters?

Is it possible to call instance methods in python 2.7 using both named and variadic arguments? I like to name parameters for clearer reading of code, but it seems like this code then fails:

def function(bob, sally, *args):
    pass

values = [1, 2, 3, 4]

function(bob="Hi bob", sally="Hello sally", *values)
like image 430
JustinHK Avatar asked Oct 09 '15 23:10

JustinHK


2 Answers

can you pass variadic arguments after named parameters?

Python 3.4.3: the answer is yes.

You must place the variadic ones first in the function definition

def function(*args, bob, sally):
    print(args, bob, sally)

values = [1, 2, 3, 4]

function(bob="Hi bob", sally="Hello sally", *values)
function(bob="Hi bob", *values, sally="Hello sally")
function(*values, bob="Hi bob", sally="Hello sally")

produces

(1, 2, 3, 4) Hi bob Hello sally
(1, 2, 3, 4) Hi bob Hello sally
(1, 2, 3, 4) Hi bob Hello sally

As you can see, you can call the function placing the parameters in any order you prefer.

Please note:

the first and second calls above work only if you pass the positional arguments via the values iterable, unpacking its contents.

Passing each positional parameter

function(bob="Hi bob", sally="Hello sally", 1, 2, 3, 4)
function(bob="Hi bob", 1, 2, 3, 4, sally="Hello sally")

isn't acceptable and produces

SyntaxError: positional argument follows keyword argument

Furthermore, since you explicitly refer to instance methods, it's worth checking what happens if function is such a method, say of class A

class A():
    def function(self, *args, bob, sally):
        print(args, bob, sally)

values = [1, 2, 3, 4]
a=A()
a.function(bob="Hi bob", sally="Hello sally", *values)
a.function(*values, bob="Hi bob", sally="Hello sally")
a.function(bob="Hi bob", *values, sally="Hello sally")

still works and produces

(1, 2, 3, 4) Hi bob Hello sally
(1, 2, 3, 4) Hi bob Hello sally
(1, 2, 3, 4) Hi bob Hello sally

Python 2.7.6: the answer is no.

>>> def function(*args, bob, sally):
  File "<stdin>", line 1
    def function(*args, bob, sally):
                          ^
SyntaxError: invalid syntax

Another approach could be to give the variadic parameters a name as well

values = {'p1': 1, 'p2': 2, 'p3': 3, 'p4': 4}

then you could define

def function(bob, sally, **kwargs):
    print(kwargs['p1'])

and call it with

function(bob="Hi bob", sally="Hello sally", **values)
like image 110
Pynchia Avatar answered Oct 04 '22 05:10

Pynchia


Yes, but with a slight modification to what you are doing:

def foo(bob="abc", sally="def", **kwargs):
    pass

foo(bob="stuff", sally="buff", other_stuff=[1, 2, 3])
like image 42
idjaw Avatar answered Oct 04 '22 04:10

idjaw