web-dev-qa-db-fra.com

Python, comment passer un argument à un paramètre de pointeur de fonction?

Je viens juste de commencer à apprendre Python et j'ai découvert que je pouvais passer une fonction comme paramètre d'une autre fonction. Maintenant, si j'appelle foo(bar()) elle ne passera pas comme pointeur de fonction mais la valeur de retour de la fonction utilisée. L'appel de foo(bar) passera la fonction, mais de cette façon je ne pourrai pas passer d'arguments supplémentaires. Que faire si je veux passer un pointeur de fonction qui appelle bar(42)?

Je veux pouvoir répéter une fonction quels que soient les arguments que je lui ai transmis.

def repeat(function, times):
    for calls in range(times):
        function()

def foo(s):
        print s

repeat(foo("test"), 4)

Dans ce cas, la fonction foo("test") est censée être appelée 4 fois de suite. Existe-t-il un moyen d'y parvenir sans avoir à passer "test" à repeat au lieu de foo?

39
Byzantian

Vous pouvez soit utiliser un lambda:

repeat(lambda: bar(42))

Ou functools.partial:

from functools import partial
repeat(partial(bar, 42))

Ou passez les arguments séparément:

def repeat(times, f, *args):
    for _ in range(times):
        f(*args)

Ce style final est assez courant dans la bibliothèque standard et les principaux outils Python. *args désigne un nombre variable d'arguments, vous pouvez donc utiliser cette fonction comme

repeat(4, foo, "test")

ou

def inquisition(weapon1, weapon2, weapon3):
    print("Our weapons are {}, {} and {}".format(weapon1, weapon2, weapon3))

repeat(10, inquisition, "surprise", "fear", "ruthless efficiency")

Notez que je mets le nombre de répétitions à l'avant pour plus de commodité. Ce ne peut pas être le dernier argument si vous souhaitez utiliser le *args construire.

(Pour être complet, vous pouvez également ajouter des arguments de mot clé avec **kwargs.)

60
Fred Foo

Vous devrez passer les paramètres de foo à la fonction de répétition:

#! /usr/bin/python3.2

def repeat (function, params, times):
    for calls in range (times):
        function (*params)

def foo (a, b):
    print ('{} are {}'.format (a, b) )

repeat (foo, ['roses', 'red'], 4)
repeat (foo, ['violets', 'blue'], 4)
17
Hyperboreus

Bien que la plupart des réponses ici soient bonnes, celle-ci pourrait être utile car elle n'introduit aucune répétition inutile et la raison des rappels est souvent de se synchroniser avec d'autres travaux en dehors du thread d'interface utilisateur principal.

Prendre plaisir!

import time, threading

def callMethodWithParamsAfterDelay(method=None, params=[], seconds=0.0):

    return threading.Timer(seconds, method, params).start()

def cancelDelayedCall(timer):

    timer.cancel()

# Example
def foo (a, b):

    print ('{} are {}'.format (a, b) )

callMethodWithParametersAfterDelay(foo, ['roses', 'red'], 0)
1
Peter Sichel