Python - przekazywanie funkcji do innej funkcji


95

Rozwiązuję zagadkę w Pythonie iw zależności od tego, którą układam, będę musiał użyć specjalnego zestawu reguł. Jak mogę przekazać funkcję do innej funkcji w Pythonie?

Przykład

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

To jest tylko pseudokod i dlatego nie jest konkretny, ale otrzymuję kod do skompilowania, ale muszę wiedzieć, jak wywołać funkcję Gamei czy jest poprawnie zdefiniowana, ponieważ reguły zostaną przełączone na albo Rule1(v)lub Rule2(v).

Odpowiedzi:


151

Po prostu podaj go jak każdy inny parametr:

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

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

print b(a,10)

44
funkcje są obiektami pierwszej klasy w Pythonie. możesz je przekazywać, włączać do dykt, list itp. Po prostu nie dodawaj nawiasów po nazwie funkcji. Na przykład dla funkcji o nazwie myfunction: myfunctionoznacza samą funkcję, myfunction()czyli wywołanie funkcji i zamiast tego pobranie jej wartości zwracanej.
nosklo

1
A co, jeśli funkcja jest metodą na obiekcie i używa właściwości tego obiektu do wykonania swojej pracy?
CpILL

2
Co się stanie, jeśli przekazane przeze mnie funkcje mają różną liczbę argumentów wejściowych? Czy powinienem zatem używać argumentów słów kluczowych?
H. Vabri,

A co, jeśli te dwie funkcje znajdują się w oddzielnych plikach Pythona?
Adrian Jimenez

25

Traktuj funkcję jako zmienną w swoim programie, aby móc łatwo przekazać ją do innych funkcji:

def test ():
   print "test was invoked"

def invoker(func):
   func()

invoker(test)  # prints test was invoked

Tak. W powyższym przykładzie invokerfunkcja musiałaby wtedy podać te argumenty podczas wywoływania funkcji.
codeape

15

Aby przekazać zarówno funkcję, jak i wszelkie argumenty do funkcji:

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)

W zależności od tego, co robisz, sensowne decoratormoże być zdefiniowanie lub użycie functools.partial.


9

Po prostu podaj to w ten sposób:

Game(list_a, list_b, Rule1)

a wtedy twoja funkcja Game mogłaby wyglądać mniej więcej tak (nadal pseudokod):

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

Nazwa funkcji może stać się nazwą zmiennej (i tym samym zostać przekazana jako argument) przez usunięcie nawiasów. Nazwa zmiennej może stać się nazwą funkcji poprzez dodanie nawiasów.

W twoim przykładzie zrównaj zmienną rulesz jedną ze swoich funkcji, pomijając nawiasy i wzmiankę o argumencie. Następnie w swojej game()funkcji wywołaj rules( v )z nawiasami i vparametrem.

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

def Game(listA, listB, rules):
    if rules( v ) == True:
        do...
    else:
        do...
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.