Вызвать функцию с списком аргументов в 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
Ответ 3
Вы можете использовать * args и ** kwargs синтаксис для аргументов переменной длины.
Что означают * args и ** kwargs?
И из официального учебника python
http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions
Ответ 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.