578

Suppose I have a function like:

def myfun(a, b, c): return (a * 2, b + c, c + b) 

Given a tuple some_tuple = (1, "foo", "bar"), how would I use some_tuple to call myfun? This should output the result (2, "foobar", "barfoo").

I know could define myfun so that it accepts the tuple directly, but I want to call the existing myfun.


See also: What do ** (double star/asterisk) and * (star/asterisk) mean in a function call? - the corresponding question for people who encounter the syntax and are confused by it.

0

5 Answers 5

1008

myfun(*some_tuple) does exactly what you request. The * operator simply unpacks the tuple (or any iterable) and passes them as the positional arguments to the function. Read more about unpacking arguments.

Sign up to request clarification or add additional context in comments.

3 Comments

The * operator simply unpacks the tuple and passes them as the positional arguments to the function. See more here: docs.python.org/3/tutorial/…
Note that the same syntax can be used for lists as well as tuples.
I've found that you can do the same with lists, (in fact, any iterable, including strings), not sure how their mutability affects things. That would be interesting to look into.
83

Note that you can also expand part of argument list:

myfun(1, *("foo", "bar")) 

3 Comments

It appears you can only do this if the expanded tuple is after the normally-provided arguments - the interpreter doesn't like it when I do this: some_func(*tuple_of_stuff, another_argument)
@Quackmatic Having the expanded tuple in any location seems to work fine in Python 3.5.1
@Quackmatic seconding @River, this works fine in Python 3.5.4: def func(a,b,c,d): print(a,b,c,d) with args = ('fee', 'fi', 'fo'); func(*args, 'fum')
16

Take a look at the Python tutorial section 4.7.3 and 4.7.4. It talks about passing tuples as arguments.

I would also consider using named parameters (and passing a dictionary) instead of using a tuple and passing a sequence. I find the use of positional arguments to be a bad practice when the positions are not intuitive or there are multiple parameters.

Comments

9

This is the functional programming method. It lifts the tuple expansion feature out of syntax sugar:

apply_tuple = lambda f, t: f(*t) 

Redefine apply_tuple via curry to save a lot of partial calls in the long run:

from toolz import curry apply_tuple = curry(apply_tuple) 

Example usage:

from operator import add, eq from toolz import thread_last thread_last( [(1,2), (3,4)], (map, apply_tuple(add)), list, (eq, [3, 7]) ) # Prints 'True' 

8 Comments

This is not helpful for a beginner. It uses third-party modules and does other confusing stuff...
toolz is third-party, is what I meant
Not every answer has to be for a beginner
For the example you gave, one can use starmap docs.python.org/3.7/library/itertools.html#itertools.starmap
This is a terrible answer
|
7

Similar to @Dominykas's answer, this is a decorator that converts multiargument-accepting functions into tuple-accepting functions:

apply_tuple = lambda f: lambda args: f(*args) 

Example 1:

def add(a, b): return a + b three = apply_tuple(add)((1, 2)) 

Example 2:

@apply_tuple def add(a, b): return a + b three = add((1, 2)) 

1 Comment

You can also just define : def add(some_tyuple: tuple) and then access with an index

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.