Wywołanie funkcji z listą argumentów w Pythonie
Próbuję wywołać funkcję wewnątrz innej funkcji w Pythonie, ale nie mogę znaleźć właściwej składni. To co chcę zrobić to coś takiego:
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])
W tym przypadku pierwsze połączenie zadziała, a drugie nie. Chcę zmodyfikować funkcję wrappera, a nie wywołane funkcje.
6 answers
Aby rozwinąć trochę inne odpowiedzi:
W linii:
def wrapper(func, *args):
* obok args
oznacza " weź resztę podanych parametrów i umieść je na liście o nazwie args
".
W linii:
func(*args)
* obok args
tutaj oznacza "weź tę listę nazwaną args i 'rozpakuj' ją do reszty parametrów.
Więc możesz wykonać następujące czynności:
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])
W wrapper2
lista jest przekazywana jawnie, ale w obu opakowaniach args
zawiera listę [1,2,3]
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-03 15:17:44
Najprostszy sposób zawijania funkcji
func(*args, **kwargs)
... jest ręczne napisanie wrappera wywołującego func () wewnątrz siebie:
def wrapper(*args, **kwargs):
# do something before
try:
return func(*a, **kwargs)
finally:
# do something after
W Pythonie funkcja jest obiektem, więc możesz przekazać jej nazwę jako argument innej funkcji i zwrócić ją. Możesz również napisać generator wrappera dla dowolnej funkcji anyFunc():
def wrapperGenerator(anyFunc, *args, **kwargs):
def wrapper(*args, **kwargs):
try:
# do something before
return anyFunc(*args, **kwargs)
finally:
#do something after
return wrapper
Należy również pamiętać, że w Pythonie, gdy nie znasz lub nie chcesz wymienić wszystkich argumentów funkcji, możesz odwołać się do krotka argumentów oznaczana nazwą, poprzedzona gwiazdką w nawiasach po nazwie funkcji:
*args
Na przykład można zdefiniować funkcję, która przyjmowałaby dowolną liczbę argumentów:
def testFunc(*args):
print args # prints the tuple of arguments
Python umożliwia jeszcze dalszą manipulację argumentami funkcji. Możesz zezwolić funkcji na przyjmowanie argumentów słów kluczowych. W ciele funkcji argumenty słów kluczowych są przechowywane w słowniku. W nawiasach po nazwie funkcji słownik ten jest oznaczony po dwóch gwiazdkach, po których następuje Nazwa słownika:
**kwargs
Podobny przykład wypisujący słowo kluczowe arguments dictionary:
def testFunc(**kwargs):
print kwargs # prints the dictionary of keyword arguments
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-24 15:18:15
Możesz używać składni *args i **kwargs dla argumentów o zmiennej długości.
Co oznaczają "args" i "kwargs"?
I z oficjalnego samouczka Pythona
Http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:41
Musisz użyć argumentów rozpakowujących..
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-03 13:53:57
Dosłowna odpowiedź na twoje pytanie (aby zrobić dokładnie to, o co prosiłeś, zmieniając tylko wrapper, a nie funkcje lub wywołania funkcji) to po prostu zmienić linię
func(args)
Do przeczytania
func(*args)
To mówi Pythonowi, aby wziął podaną listę (w tym przypadku args
) i przekazał jej zawartość funkcji jako argumenty pozycyjne.
Ten trik działa po obu "stronach" wywołania funkcji, więc funkcja zdefiniowana tak:
def func2(*args):
return sum(args)
Byłby w stanie przyjąć jak najwięcej argumenty pozycyjne, gdy je rzucasz, i umieść je wszystkie na liście o nazwie args
.
**
zamiast *
.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-03 19:48:20
Mały dodatek do poprzednich odpowiedzi, ponieważ nie mogłem znaleźć rozwiązania problemu, co nie jest warte otwierania nowego pytania, ale doprowadziło mnie tutaj.
Oto mały fragment kodu, który łączy lists
, zip()
i *args
, aby zapewnić wrapper, który może radzić sobie z nieznaną ilością funkcji z nieznaną ilością argumentów.
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)
Należy pamiętać, że zip()
nie zapewnia kontroli bezpieczeństwa dla list o nierównej długości, patrz Iteratory zip twierdzące o równej długości w python .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:08