Вызвать функцию с списком аргументов в python

Я пытаюсь вызвать функцию внутри другой функции в python, но не могу найти правильный синтаксис. Я хочу сделать что-то вроде этого:

def wrapper(func, args):
    func(args)

def func1(x):
    print(x)

def func2(x, y, z):
    return x+y+z

wrapper(func1, [x])
wrapper(func2, [x, y, z])

В этом случае первый вызов будет работать, а второй - нет. Я хочу изменить функцию-оболочку, а не вызываемые функции.

Ответ 1

Чтобы немного рассказать о других ответах:

В строке:

def wrapper(func, *args):

* рядом с args означает "взять остальные параметры и поместить их в список с именем args".

В строке:

    func(*args)

* рядом с args здесь означает "взять этот список, называемый args, и" развернуть "его в остальные параметры.

Итак, вы можете сделать следующее:

def wrapper1(func, *args): # with star
    func(*args)

def wrapper2(func, args): # without star
    func(*args)

def func2(x, y, z):
    print x+y+z

wrapper1(func2, 1, 2, 3)
wrapper2(func2, [1, 2, 3])

В wrapper2 список передается явно, но в обеих оболочках args содержится список [1,2,3].

Ответ 2

Самый простой способ обернуть функцию

    func(*args, **kwargs)

... заключается в том, чтобы вручную написать оболочку, которая вызовет функцию func() внутри себя:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after

В функции Python есть объект, поэтому вы можете передать его имя как аргумент другой функции и вернуть его. Вы также можете написать генератор wraper для любой функции anyFunc():

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper

Также обратите внимание, что в Python, когда вы не знаете или не хотите называть все аргументы функции, вы можете ссылаться на кортеж аргументов, который обозначается его именем, которому предшествует звездочка в круглых скобках после имени функции:

    *args

Например, вы можете определить функцию, которая принимает любое количество аргументов:

    def testFunc(*args):
        print args    # prints the tuple of arguments

Python обеспечивает возможность манипуляции с функциями funter для аргументов функции. Вы можете разрешить функции принимать аргументы ключевых слов. Внутри тела функции аргументы ключевого слова хранятся в словаре. В скобках arter имя функции этого словаря обозначается двумя звездочками, за которыми следует имя словаря:

    **kwargs

Аналогичный пример, который печатает словарь аргументов аргументов ключевого слова:

    def testFunc(**kwargs):
        print kwargs    # prints the dictionary of keyword arguments

Ответ 4

Вам нужно использовать распаковку аргументов.

def wrapper(func, *args):
    func(*args)

def func1(x):
    print(x)

def func2(x, y, z):
    print x+y+z

wrapper(func1, 1)
wrapper(func2, 1, 2, 3)

Ответ 5

Буквальный ответ на ваш вопрос (чтобы сделать то, что вы просили, изменяя только оболочку, а не функции или вызовы функций) просто изменить строку

func(args)

читать

func(*args)

Это говорит Python взять список (в этом случае args) и передать его содержимое функции в качестве позиционных аргументов.

Этот трюк работает на обеих сторонах вызова функции, поэтому функция определяется следующим образом:

def func2(*args):
    return sum(args)

мог бы принять столько позиционных аргументов, сколько вы набросите на него, и поместить их в список с именем args.

Надеюсь, это поможет немного прояснить ситуацию. Обратите внимание, что это возможно и с аргументами dicts/keyword, используя ** вместо *.

Ответ 6

Небольшое дополнение к предыдущим ответам, так как я не мог найти решение проблемы, которая не стоит открывать новый вопрос, но привела меня сюда.

Вот небольшой фрагмент кода, который объединяет lists, zip() и *args, чтобы предоставить оболочку, которая может работать с неизвестным количеством функций с неизвестным количеством аргументов.

def f1(var1, var2, var3):
    print(var1+var2+var3)

def f2(var1, var2):
    print(var1*var2)

def f3():
    print('f3, empty')

def wrapper(a,b, func_list, arg_list):
    print(a)
    for f,var in zip(func_list,arg_list):
        f(*var)
    print(b)

f_list = [f1, f2, f3]
a_list = [[1,2,3], [4,5], []]

wrapper('begin', 'end', f_list, a_list)

Имейте в виду, что zip() не обеспечивает проверку безопасности для списков неравной длины, см. zip-итераторы, утверждающие равную длину в python.