Python - Passer une fonction dans une autre fonction

92

Je résous un puzzle en utilisant python et en fonction du puzzle que je résous, je devrai utiliser un ensemble spécial de règles. Comment puis-je passer une fonction dans une autre fonction en Python?

Exemple

def Game(listA, listB, rules):
   if rules == True:
      do...
   else:
      do...

def Rule1(v):
  if "variable_name1" in v:
      return False
  elif "variable_name2" in v:
      return False
  else:
      return True

def Rule2(v):
  if "variable_name3" and "variable_name4" in v:
      return False
  elif "variable_name4" and variable_name1 in v:
      return False
  else:
      return True

Ceci est juste un pseudo code et donc pas spécifique mais je reçois le code à compiler mais j'ai besoin de savoir comment appeler la fonction Gameet si elle est correctement définie puisque les règles seront commutées pour l'un Rule1(v)ou l' autre Rule2(v).

jchanger
la source

Réponses:

148

Passez-le simplement comme n'importe quel autre paramètre:

def a(x):
    return "a(%s)" % (x,)

def b(f,x):
    return f(x)

print b(a,10)
John Millikin
la source
43
les fonctions sont des objets de première classe en python. vous pouvez les faire circuler, les inclure dans des dictionnaires, des listes, etc. N'incluez simplement pas les parenthèses après le nom de la fonction. Exemple, pour une fonction nommée myfunction: myfunctionsignifie la fonction elle-même, myfunction()signifie appeler la fonction et obtenir sa valeur de retour à la place.
nosklo
1
Et si la fonction est une méthode sur un objet et utilise une propriété de cet objet pour faire son travail?
CpILL
2
Que faire si les fonctions que je passe ont un nombre variable d'arguments d'entrée? Dois-je alors utiliser des arguments de mots-clés?
H.Vabri
Que faire si les deux fonctions sont dans des fichiers Python séparés?
Adrian Jimenez
24

Traitez la fonction comme une variable dans votre programme afin de pouvoir les passer facilement à d'autres fonctions:

def test ():
   print "test was invoked"

def invoker(func):
   func()

invoker(test)  # prints test was invoked
Piotr Czapla
la source
Oui. Dans l'exemple ci-dessus, la invokerfonction devra alors fournir ces arguments lors de l'appel de la fonction.
codeape
15

Pour passer à la fois une fonction et des arguments à la fonction:

from typing import Callable    

def looper(fn: Callable, n:int, *args, **kwargs):
    """
    Call a function `n` times

    Parameters
    ----------
    fn: Callable
        Function to be called.
    n: int
        Number of times to call `func`.
    *args
        Positional arguments to be passed to `func`.
    **kwargs
        Keyword arguments to be passed to `func`.

    Example
    -------
    >>> def foo(a:Union[float, int], b:Union[float, int]):
    ...    '''The function to pass'''
    ...    print(a+b)
    >>> looper(foo, 3, 2, b=4)
    6
    6
    6       
    """
    for i in range(n):
        fn(*args, **kwargs)

Selon ce que vous faites, il peut être judicieux de définir un decorator, ou peut-être utiliser functools.partial.

Ryanjdillon
la source
9

Passez-le simplement, comme ceci:

Game(list_a, list_b, Rule1)

et alors votre fonction de jeu pourrait ressembler à quelque chose comme ceci (toujours pseudocode):

def Game(listA, listB, rules=None):
    if rules:
        # do something useful
        # ...
        result = rules(variable) # this is how you can call your rule
    else:
        # do something useful without rules
Ian Clelland
la source
9

Un nom de fonction peut devenir un nom de variable (et donc être passé en argument) en supprimant les parenthèses. Un nom de variable peut devenir un nom de fonction en ajoutant les parenthèses.

Dans votre exemple, assimilez la variable rulesà l'une de vos fonctions, en laissant de côté les parenthèses et la mention de l'argument. Puis dans votre game()fonction, invoquez rules( v )avec les parenthèses et le vparamètre.

if puzzle == type1:
    rules = Rule1
else:
    rules = Rule2

def Game(listA, listB, rules):
    if rules( v ) == True:
        do...
    else:
        do...
Ken
la source