Python: passaggio di una funzione in un'altra funzione


92

Sto risolvendo un puzzle usando Python e, a seconda del puzzle che sto risolvendo, dovrò usare una serie speciale di regole. Come posso passare una funzione in un'altra funzione in Python?

Esempio

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

Questo è solo uno pseudo codice e quindi non specifico, ma ottengo il codice da compilare ma ho bisogno di sapere come chiamare la funzione Gamee se è definita correttamente poiché le regole verranno cambiate per Rule1(v)o Rule2(v).

Risposte:


148

Basta passarlo come qualsiasi altro parametro:

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

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

print b(a,10)

43
le funzioni sono oggetti di prima classe in python. puoi passarli in giro, includerli in dict, elenchi, ecc. Basta non includere le parentesi dopo il nome della funzione. Esempio, per una funzione denominata myfunction: myfunctionsignifica la funzione stessa, myfunction()significa chiamare la funzione e ottenere invece il suo valore di ritorno.
nosklo

1
E se la funzione è un metodo su un oggetto e utilizza una proprietà di quell'oggetto per svolgere il suo lavoro?
CpILL

2
Cosa succede se le funzioni che passo hanno un numero variabile di argomenti di input? Dovrei quindi utilizzare argomenti di parole chiave?
H. Vabri

E se le due funzioni sono in file Python separati?
Adrian Jimenez

24

Considera le funzioni come variabili nel tuo programma in modo da poterle passare facilmente ad altre funzioni:

def test ():
   print "test was invoked"

def invoker(func):
   func()

invoker(test)  # prints test was invoked

Sì. Nell'esempio sopra, la invokerfunzione dovrebbe quindi fornire quegli argomenti quando chiama la funzione.
codeape

15

Per passare sia una funzione che qualsiasi argomento alla funzione:

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)

A seconda di ciò che stai facendo, potrebbe avere senso definire un decorator, o forse utilizzare functools.partial.


9

Basta passarlo, in questo modo:

Game(list_a, list_b, Rule1)

e quindi la tua funzione di gioco potrebbe assomigliare a questo (ancora pseudocodice):

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

9

Un nome di funzione può diventare un nome di variabile (e quindi essere passato come argomento) trascinando le parentesi. Un nome di variabile può diventare un nome di funzione aggiungendo le parentesi.

Nel tuo esempio, equipara la variabile rulesa una delle tue funzioni, tralasciando le parentesi e la menzione dell'argomento. Quindi nella tua game()funzione, invoca rules( v )con le parentesi e il vparametro.

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

def Game(listA, listB, rules):
    if rules( v ) == True:
        do...
    else:
        do...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.