Python - Truyền một hàm vào một hàm khác


92

Tôi đang giải một câu đố bằng python và tùy thuộc vào câu đố mà tôi đang giải, tôi sẽ phải sử dụng một bộ quy tắc đặc biệt. Làm cách nào để chuyển một hàm vào một hàm khác trong Python?

Thí dụ

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

Đây chỉ là một mã giả và do đó không cụ thể nhưng tôi lấy mã để biên dịch nhưng tôi cần biết cách gọi hàm Gamevà liệu nó có được xác định chính xác hay không vì các quy tắc sẽ được chuyển cho một trong hai Rule1(v)hoặc Rule2(v).

Câu trả lời:


147

Chỉ cần chuyển nó vào giống như bất kỳ tham số nào khác:

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

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

print b(a,10)

43
các hàm là các đối tượng hạng nhất trong python. bạn có thể chuyển chúng xung quanh, bao gồm chúng trong các phần, danh sách, v.v. Chỉ cần không bao gồm dấu ngoặc đơn sau tên hàm. Ví dụ, đối với một hàm được đặt tên myfunction: myfunctioncó nghĩa là chính hàm đó, myfunction()có nghĩa là gọi hàm và nhận giá trị trả về của nó để thay thế.
nosklo

1
Và điều gì sẽ xảy ra nếu hàm là một phương thức trên một đối tượng và sử dụng một thuộc tính của đối tượng đó để thực hiện công việc của nó?
CpILL

2
Điều gì sẽ xảy ra nếu các hàm tôi truyền có số lượng đối số đầu vào khác nhau? Sau đó tôi có nên sử dụng các đối số từ khóa không?
H. Vabri

Điều gì sẽ xảy ra nếu hai hàm nằm trong các tệp python riêng biệt?
Adrian Jimenez

24

Coi hàm như một biến trong chương trình của bạn để bạn có thể chuyển chúng sang các hàm khác một cách dễ dàng:

def test ():
   print "test was invoked"

def invoker(func):
   func()

invoker(test)  # prints test was invoked

Đúng. Trong ví dụ trên, invokerhàm sẽ cần cung cấp các đối số đó khi gọi hàm.
codeape

15

Để truyền cả một hàm và bất kỳ đối số nào cho hàm:

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)

Tùy thuộc vào những gì bạn đang làm, nó có thể hợp lý để xác định một decoratorhoặc có thể sử dụng functools.partial.


9

Chỉ cần chuyển nó vào, như thế này:

Game(list_a, list_b, Rule1)

và sau đó chức năng Trò chơi của bạn có thể trông giống như sau (vẫn là mã giả):

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

Một tên hàm có thể trở thành một tên biến (và do đó được chuyển như một đối số) bằng cách bỏ dấu ngoặc đơn. Tên biến có thể trở thành tên hàm bằng cách thêm dấu ngoặc đơn.

Trong ví dụ của bạn, hãy đánh đồng biến rulesvới một trong các hàm của bạn, bỏ dấu ngoặc đơn và đề cập đến đối số. Sau đó, trong game()hàm của bạn , gọi rules( v )bằng dấu ngoặc đơn và vtham số.

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

def Game(listA, listB, rules):
    if rules( v ) == True:
        do...
    else:
        do...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.