J'essaie d'appeler une fonction dans une autre fonction en python, mais je ne trouve pas la bonne syntaxe. Ce que je veux faire est quelque chose comme ceci:
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])
Dans ce cas, le premier appel fonctionnera et le second ne fonctionnera pas. Ce que je veux modifier, c’est la fonction wrapper et non les fonctions appelées.
Pour développer un peu sur les autres réponses:
Dans la ligne:
def wrapper(func, *args):
Le * à côté de args
signifie "prend le reste des paramètres donnés et les place dans une liste appelée args
".
Dans la ligne:
func(*args)
Le * à côté de args
signifie ici "prenez cette liste appelée args et" décompressez-la "dans le reste des paramètres.
Donc, vous pouvez faire ce qui suit:
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])
Dans wrapper2
, la liste est explicitement transmise, mais dans les deux wrappers args
contient la liste [1,2,3]
.
La manière la plus simple d'envelopper une fonction
func(*args, **kwargs)
... est d'écrire manuellement un wrapper qui appellerait func () à l'intérieur de lui-même:
def wrapper(*args, **kwargs):
# do something before
try:
return func(*a, **kwargs)
finally:
# do something after
Dans Python, la fonction étant un objet, vous pouvez transmettre son nom en tant qu'argument d'une autre fonction et le renvoyer. Vous pouvez également écrire un générateur de wrapper pour toute fonction anyFunc ():
def wrapperGenerator(anyFunc, *args, **kwargs):
def wrapper(*args, **kwargs):
try:
# do something before
return anyFunc(*args, **kwargs)
finally:
#do something after
return wrapper
Veuillez également noter que, dans Python, lorsque vous ne connaissez pas ou ne souhaitez pas nommer tous les arguments d'une fonction, vous pouvez faire référence à un tuple d'arguments, désigné par son nom, précédé de un astérisque entre parenthèses après le nom de la fonction:
*args
Par exemple, vous pouvez définir une fonction qui prendrait un nombre quelconque d’arguments:
def testFunc(*args):
print args # prints the Tuple of arguments
Python permet une manipulation encore plus poussée des arguments de fonction. Vous pouvez autoriser une fonction à prendre des arguments de mots clés. Dans le corps de la fonction, les arguments de mots-clés sont conservés dans un dictionnaire. Entre les parenthèses après le nom de la fonction, ce dictionnaire est désigné par deux astérisques suivis du nom du dictionnaire:
**kwargs
Un exemple similaire qui affiche le dictionnaire des mots clés:
def testFunc(**kwargs):
print kwargs # prints the dictionary of keyword arguments
La réponse littérale à votre question (faire exactement ce que vous avez demandé, ne changer que l'encapsuleur, pas les fonctions ou les appels de fonction) consiste simplement à modifier la ligne.
func(args)
lire
func(*args)
Ceci indique à Python de prendre la liste donnée (dans ce cas, args
) et de transmettre son contenu à la fonction sous forme d'arguments de position.
Cette astuce fonctionne des deux "côtés" de l'appel de fonction, donc une fonction définie comme ceci:
def func2(*args):
return sum(args)
serait capable d’accepter autant d’arguments de position que vous le feriez et de les placer tous dans une liste appelée args
.
J'espère que cela aide à clarifier un peu les choses. Notez que tout cela est également possible avec les arguments dicts/mot-clé, en utilisant **
au lieu de *
.
Vous pouvez utiliser la syntaxe * args et ** kwargs pour les arguments de longueur variable.
Que signifient * args et ** kwargs?
Et du tutoriel officiel python
http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions
Vous devez utiliser des arguments en décompressant ..
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)
Un petit ajout aux réponses précédentes, car je ne pouvais pas trouver de solution à un problème, ce qui ne vaut pas la peine d'ouvrir une nouvelle question, mais m'a conduit ici.
Voici un petit extrait de code, qui associe lists
, Zip()
et *args
, afin de fournir un wrapper pouvant traiter un nombre inconnu de fonctions avec un nombre inconnu d'arguments.
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)
Gardez à l'esprit que Zip()
ne fournit pas de contrôle de sécurité pour les listes de longueur inégale, voir Les itérateurs Zip affirmant une longueur égale en python .