Расширяя кортежи в аргументы

411

Есть ли способ расширить кортеж Python в функцию - в качестве фактических параметров?

Например, вот expand()волшебство:

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

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

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

Я знаю, что можно определить myfunкак myfun((a, b, c)), но, конечно, может быть устаревший код. Спасибо

AkiRoss
источник

Ответы:

734

myfun(*some_tuple)делает именно то, что вы просите. *Оператор просто распаковывает кортеж (или любую итерацию) и передает их в качестве позиционных аргументов функции. Узнайте больше о распаковке аргументов .

Алекс Мартелли
источник
8
Оператор * просто распаковывает кортеж и передает его в качестве позиционных аргументов функции. Подробнее здесь: docs.python.org/3/tutorial/…
john_mc
4
Обратите внимание, что один и тот же синтаксис может использоваться как для списков, так и для кортежей.
brendon-ai
Я обнаружил, что вы можете сделать то же самое со списками (фактически любой итерируемой, включая строки), не зная, как их изменчивость влияет на вещи. Это было бы интересно посмотреть.
wcyn
52

Обратите внимание, что вы также можете расширить часть списка аргументов:

myfun(1, *("foo", "bar"))
Valentas
источник
13
Похоже, что вы можете сделать это только в том случае, если расширенный кортеж следует за обычно предоставленными аргументами - интерпретатору не нравится, когда я делаю это:some_func(*tuple_of_stuff, another_argument)
Том Галвин,
6
@Quackmatic Наличие расширенного кортежа в любом месте прекрасно работает в Python 3.5.1
River
1
@ Quackmatic secondding @River, это прекрасно работает в Python 3.5.4: def func(a,b,c,d): print(a,b,c,d)сargs = ('fee', 'fi', 'fo'); func(*args, 'fum')
R. Navega
15

Взгляните на разделы 4.7.3 и 4.7.4 учебника по Python . Это говорит о передаче кортежей в качестве аргументов.

Я также хотел бы рассмотреть использование именованных параметров (и передачу словаря) вместо использования кортежа и передачи последовательности. Я считаю использование позиционных аргументов плохой практикой, когда позиции не интуитивны или есть несколько параметров.

Uri
источник
8

Это метод функционального программирования. Он поднимает функцию расширения кортежа из синтаксического сахара:

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

Пример использования:

from toolz import * 
from operator import add, eq

apply_tuple = curry(apply_tuple)

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

Карри redefiniton из apply_tupleэкономит много partialзвонков в долгосрочной перспективе.

Доминикас Мостаускис
источник
5
Это не полезно для начинающего. Он использует сторонние модули и делает другие запутанные вещи ...
gberger
gberger, lambda f, t: f(*t)не использует сторонние модули, я новичок в Python, и это полезно для меня. Это чисто функциональный подход. Если вы не используете этот стиль, тогда этот ответ не для вас.
Доминикас Мостаускис
1
Toolz является сторонним, вот что я имел в виду
gberger
5
Не каждый ответ должен быть для начинающего
Джордан
1
Для приведенного вами примера можно использовать starmap docs.python.org/3.7/library/itertools.html#itertools.starmap
Bo.