469
votes

Is there a way to expand a Python tuple into a function - as actual parameters?

For example, here expand() does the magic:

some_tuple = (1, "foo", "bar")

def myfun(number, str1, str2):
    return (number * 2, str1 + str2, str2 + str1)

myfun(expand(some_tuple)) # (2, "foobar", "barfoo")

I know one could define myfun as myfun((a, b, c)), but of course there may be legacy code. Thanks

5

5 Answers

823
votes

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.

56
votes

Note that you can also expand part of argument list:

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

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.

8
votes

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'
2
votes

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))