programing

함수(콜백)를 다른 함수의 인수로 사용하는 것은 파이썬에서 어떻게 작동합니까?

magicmemo 2023. 9. 8. 21:21
반응형

함수(콜백)를 다른 함수의 인수로 사용하는 것은 파이썬에서 어떻게 작동합니까?

다음과 같은 코드가 있다고 가정해 보겠습니다.

def myfunc(anotherfunc, extraArgs):
    # somehow call `anotherfunc` here, passing it the `extraArgs`
    pass

나는 다른 기존 기능을 전달하고 싶습니다.anotherfunc,고의록는다은과다과은st는e수,록rapfd, .extraArgs, 가지고 있습니다myfunc전달된 함수를 해당 인수와 함께 호출합니다.

가능한가요?어떻게 하면 되죠?

네, 가능합니다.myfunc는 전달받은 함수를 다음과 같이 호출할 수 있습니다.

def myfunc(anotherfunc, extraArgs):
    anotherfunc(*extraArgs)

완전히 작동된 예는 다음과 같습니다.

>>> def x(a, b):
...     print('a:', a, 'b:', b)
... 
>>> def y(z, t):
...     z(*t)
... 
>>> y(x, ('hello', 'manuel'))
a: hello b: manuel

다른 방법은 다음과 같습니다.*args 선택적으로 (선택사항및**kwargs으):

def a(x, y):
    print(x, y)

def b(other, function, *args, **kwargs):
    function(*args, **kwargs)
    print(other)

b('world', a, 'hello', 'dude')

산출량

hello dude
world

:function,*args,그리고.**kwargs 인수여야 당로야의막야다며다(야t막 ( )b) 다음과 같이 말합니다.function.

파이썬의 함수는 1등급 객체입니다.그러나 함수 정의는 약간 달라야 합니다.

def myfunc(anotherfunc, extraArgs, extraKwArgs):
    return anotherfunc(*extraArgs, **extraKwArgs)

물론, 이것이 python이 첫 번째 매개 변수가 함수인 다음과 같은 메소드를 구현하는 이유입니다.

  • map(function, iterable, ...) -용한에를고과을다든다을과y고를a에든f-o한m용denf
  • filter(function, iterable)가 true를 하는 반복 -를 true는복한로다을가다을로는를t한복가emarfes
  • reduce(function, iterable [,initializer])-두의로에다를다fs-의 항목에 두 합니다.iterable으로 이동하여 수 있도록
  • 양고기

함수는 다른 함수에 대한 매개 변수가 될 수 있고, 함수는 다른 함수를 반환할 수 있습니다.

다음은 예입니다.

def out_func(a):
    def in_func(b):
        print(a + b + b + 3)
    return in_func
 
obj = out_func(1)
print(obj(5)) # outputs 14

데코레이터는 프로그래머가 함수를 인수로 전달하고, 다른 함수 안에서 하나의 함수를 정의할 수 있기 때문에 파이썬에서 매우 강력합니다.

def decorator(func):
    def insideFunction():
        print("This is inside function before execution")
        func()
    return insideFunction

def func():
    print("I am argument function")

func_obj = decorator(func) 
func_obj()

출력:

This is inside function before execution
I am argument function

한 함수에 대한 호출을 다른 함수에 대한 인수로 사용하여 두 개 이상의 함수를 동시에 호출할 수 있습니다.

def anotherfunc(inputarg1, inputarg2):
    pass
def myfunc(func = anotherfunc):
    print(func)

myfunc(anotherfunc(inputarg1, inputarg2))

이는 원인이 될 것입니다.myfunc을다eee을에서 반환 값을 인쇄하다anotherfunc다즉))None).

합니다. 합니다, .다른 기능과 마찬가지로 이 기능을 사용합니다.anotherfunc(*extraArgs).

요약

네, 가능합니다.

인 에서에서는,anotherfunc개에 대한 매개 myfunc는 콜백의 한 예입니다.myfunc따라서, 는 고차 함수(이하, HOF)의 예입니다.

HOF를 작성하고 콜백을 제공하는 식의 양 측면의 간단한 예는 다음과 같습니다.

def higher_order(a_callback):
    print("I will call:", a_callback)
    a_callback()

def my_callback():
    print("my_callback was called")

higher_order(my_callback)

는 가 을 합니다 합니다 가 을 )my_callback- 함수 이름만 사용하고 괄호는 사용하지 않습니다.잘못쓰기higher_order(my_callback()) 먼저 전화를 걸어 반환 값(여기서는)다음으로 전달합니다.higher_order. 호출할 수 없으므로 이로 인해 가 발생합니다.

함수 자체에서는 다른 함수를 매개변수로 받아들이거나, 함수를 호출하여 사용하기 위해서는 특별한 조치를 취할 필요가 없습니다.안에서.higher_order,a_callback는된의컬다기(기다,,my_callback의 이름, )을됩니다; 은 의 을 으로써 으로써 을 의 은 ( 논법, , , , , , , , , , )입니다; 입니다 입니다 .higher_order전달된 함수를 사용하려면 해야 합니다.

HOF 쓰기

우리가 다음을 정의하려고 시도한다고 가정하자.def my_func(other_func, func_args):where, other_func콜백이 될 겁니다함수 내에서,other_func는 단순히 전달된 콜백의 이름이며, 호출은 다른 함수를 호출하는 것과 동일하게 작동합니다.이름(또는 호출해야 할 호출 가능자를 평가하는 다른 표현)이 필요합니다.(통화에 , 에는 에 을 하고 에는 에는 하고 을 .)를 들면. 예를 들면. 를 과 합니다 합니다 과 를 .func_args호출자에 대한 변수 인수의 시퀀스가 되어야 하며, 우리는 통화에서 인수를 풀어서 이 통화를 할 수 있습니다.따라서:

def my_func(other_func, func_args):
    other_func(*func_args)

은 로 가 한 은 될 로부터 할 를 할 로 를 dict매핑), 할 수 핑는수할는에른가는(수(k할는,f에른rseghoe,**짐을 풉니다따라서:

def my_func(other_func, func_args, func_kwargs):
    other_func(*func_args, **func_kwargs)

물론 우리는 그런 기본적인 논리에 결코 국한되지 않습니다.my_func다른 기능과 마찬가지로 작동합니다.전화하기 전이나 후에 다른 임의의 일을 할 수 있습니다.other_func; 할 수 있습니다return면른로fe면r른eee으로other_func과를 부를 도 있고;할을 부를 수도 있습니다.other_func번 아님); 할 수 한번상는혀님를할수다도해개를지은에을음수과고서할기를로e도를지개을음수(은(tto다rdn;es)loe ).func_args아니면func_kwargs전혀) 등.

HOF에 콜백 함수 전달

이 HOF를 사용하기 위해 호출 코드는 콜백으로 전달할 수 있는 적절한 호출 코드(즉, 해당 서명이 HOF가 호출하는 방식과 호환되어야 함)와 HOF 자체에 대한 호출을 위한 적절한 코드가 필요합니다.

위의 예를 계속해서 들어, 다음과 같은 콜백이 있다고 가정합니다.

def my_callback(a, b, /, **c):
    print(f'a = {a}; b = {b}; c = {c}')

부터부터my_func을 사용할 입니다.*그리고.** ① ② ③ ④ ⑤ 의 서명에는 특별한 .my_callback그 이후로. my_func 됩니다.a그리고.b*func_args 이후로, 로 my_func 이 매개 변수를 위치 전용으로 표시합니다.func_args에게 my_func 이 2가다의다가(fl ).func_kwargs어쨌든 사전이 되어야 합니다. 콜백에 대한 콜백을 위해 압축이 풀린 다음 콜백에서 다시 포장합니다.

따라서:

def my_func(other_func, func_args, func_kwargs):
    other_func(*func_args, **func_kwargs)

def my_callback(a, b, /, **c):
    print(f'a = {a}; b = {b}; c = {c}')

# call `my_func`, giving it the callback `my_callback`
# as well as appropriate arguments to call the callback:
my_func(my_callback, [1, 2], {'example': 3})

다른 종류의 콜백

HOF는 단순히 콜백을 호출하기 때문에 콜백이 기능인지 여부는 실제로 중요하지 않습니다.오리 타이핑의 이점을 이용하여, 우리는 또한 예를 들어 수업을 통과할 수 있습니다.이 기능은 "유형 검사"(예: 표준 라이브러리)를 위해 콜백을 사용하는 HOF에 특히 유용합니다.argparse이렇게 함):

def ask_user_for_value(type_checker):
    while True:
        try:
            return type_checker(input('give me some input: '))
        except Exception as e:
            print(f'invalid input ({e}); try again')

# using an existing type:
ask_user_for_value(int)

# using a custom function for verification:
def capital_letter(text):
    if len(text) != 1:
        raise ValueError('not a single character')
    if not (text.isupper() and text.isalpha()):
        raise ValueError('not an uppercase letter')
    return text

ask_user_for_value(capital_letter)

# using an enum: (in 3.11 this could use StrEnum)
from enum import Enum
class Example(Enum):
    ONE = 'one'
    TWO = 'two'

ask_user_for_value(Example)

# using a bound method of an instance:
class Exact: # only allow the specified string
    def __init__(self, value):
        self._value = value

    def check(self, value):
        if value != self._value:
            raise ValueError(f'must be {self._value!r}')
        return value

ask_user_for_value(Exact('password').check)

콜백을 사용하는 다른 방법

하는 것 하는 는 에 될 에도 를 될 에 하는 예를 들어,list,dict또는 클래스 인스턴스의 속성으로 사용할 수 있습니다.핵심 통찰력은 파이썬에서 함수는 객체이기 때문에 이런 식으로 저장할 수 있고 함수 객체를 평가하는 표현은 함수를 호출하는 데 사용할 수 있다는 입니다.

예:

def my_callback():
    print('my_callback was called')

# in a list
funcs = [my_callback]
for i in funcs:
    i()

# in a dict
funcs = {'my_callback': my_callback}
funcs['my_callback']()

# in a class instance
class Example:
    def __init__(self, callback):
        self._callback = callback

    def use_callback(self):
        self._callback()

instance = Example()
instance.use_callback()

특별한 경우: HOF가 하지 않을 주장 제공

때로는 기존 콜백 함수를 사용하고 싶지만 HOF가 제공하는 것 외에 추가 인수가 필요합니다.타사 코드에서 나온 HOF로 작업할 때 특히 중요합니다.많은 라이브러리가 콜백(예: 표준 라이브러리)으로 전달하기 위해 임의의 매개 변수를 허용하도록 특별히 설계되었지만 다른 라이브러리는 그렇지 않습니다(예: 테스트할 코드에 문자열이 아닌 호출 가능한 표준 라이브러리 모듈 사용).

후자의 경우 인수를 HOF에 전달하기 전에 콜백에 "결합"되어야 합니다.

이 방법에 대해서Python Argument Binders참조하십시오. 이 방법은 이 답변의 범위를 벗어납니다.

에 다른 에 으로 하기 될 에도 됩니다 가 이 됩니다 가 에도 이 될 :commandTkinter)에서 를 생성할 때 제공됩니다.

def x(a):
    print(a)
    return a

def y(a):
    return a

y(x(1))

다음은 예입니다.

def x(a):
    print(a)
    return a

def y(func_to_run, a):
    return func_to_run(a)

y(x, 1)

언급URL : https://stackoverflow.com/questions/6289646/how-does-using-a-function-callback-as-an-argument-to-another-function-work-in

반응형