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

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

Например, здесь expand() делает магию:

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

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

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

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

Ответ 1

myfun(*tuple) делает именно то , что вы запрашиваете.

Побочная проблема: не используйте в качестве идентификаторов встроенные имена типов, такие как tuple, list, file, set и т.д. - это ужасная практика, и она вернется и укусит вас, когда вы меньше всего этого ожидаете, поэтому просто зайдите в привычка активно избегать сокрытия встроенных имен с вашими собственными идентификаторами.

Ответ 2

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

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

Ответ 3

Посмотрите учебник Python, раздел 4.7.3 и 4.7.4. Он говорит о передаче кортежей в качестве аргументов.

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

Ответ 4

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

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'

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

Ответ 5

Я столкнулся с подобной проблемой и создал эту функцию, которая расширяет фиксированную функцию. Надеюсь это поможет.

def run_argtup(func, argvalues):
    """
    Execute any functions with their arguments in tuple.

    :param func:
    :param argvalues:
    :return:
    """
    argnames = get_func_argnames(func)
    if len(argnames) != len(argvalues):
        raise ValueError("Length of args doens't match.")
    for argn, argv in zip(argnames, argvalues):
        exec('{}=argv'.format(argn))
    return eval('func(%s, %s)' % argnames)