首頁 > 軟體

徹底弄懂Python中的回撥函數(callback)

2022-06-24 18:02:01

摘要

主要是介紹python 的回撥函數callback。

什麼是回撥函數

當程式執行是,一般情況下,應用程式會時常通過API呼叫庫裡所預先備好的函數。但是有些庫函數卻要求應用先傳給它一個函數,好在合適的時候呼叫,以完成目標任務。這個被傳入的、後又被呼叫的函數就稱為回撥函數(callback function)

例如:

有一家旅館提供叫醒服務,但是要求旅客自己決定叫醒的方法。可以是打客房電話,也可以是派服務員去敲門,睡得死怕耽誤事的,還可以要求往自己頭上澆盆水。這裡,“叫醒”這個行為是旅館提供的,相當於庫函數,但是叫醒的方式是由旅客決定並告訴旅館的,也就是回撥函數。而旅客告訴旅館怎麼叫醒自己的動作,也就是把回撥函數傳入庫函數的動作,稱為登記回撥函數(to register a callback function)

可以看到,回撥函數通常和應用處於同一抽象層(因為傳入什麼樣的回撥函數是在應用級別決定的)。而回撥就成了一個高層呼叫底層,底層再回過頭來呼叫高層的過程。(我認為)這應該是回撥最早的應用之處,也是其得名如此的原因。

回撥機制的優勢

回撥機制提供了非常大的靈活性。我們把圖中的庫函數改稱為中間函數了,這是因為回撥並不僅僅用在應用和庫之間。任何時候,只要想獲得類似於上面情況的靈活性,都可以利用回撥。有的同學可定想回撥似乎只是函數間的呼叫,可以發現兩者之間的一個關鍵的不同

在回撥中,我們利用某種方式,把回撥函數像引數一樣傳入中間函數。可以這麼理解,在傳入一個回撥函數之前,中間函數是不完整的。換句話說,程式可以在執行時,通過登記不同的回撥函數,來決定、改變中間函數的行為。這就比簡單的函數呼叫要靈活太多了。

#回撥函數1
#生成一個2k形式的偶數
def double(x):
    return x * 2
    
#回撥函數2
#生成一個4k形式的偶數
def quadruple(x):
    return x * 4
 
callback_demo.py`
 
from even import *
 
#中間函數
#接受一個生成偶數的函數作為引數
#返回一個奇數
def getOddNumber(k, getEvenNumber):
    return 1 + getEvenNumber(k)
    
#起始函數,這裡是程式的主函數
def main():    
    k = 1
    #當需要生成一個2k+1形式的奇數時
    i = getOddNumber(k, double)
    print(i)
    #當需要一個4k+1形式的奇數時
    i = getOddNumber(k, quadruple)
    print(i)
    #當需要一個8k+1形式的奇數時
    i = getOddNumber(k, lambda x: x * 8)
    print(i)
    
if __name__ == "__main__":
    main()

非同步處理有關的回撥函數

def apply_ascyn(func, args, callback):
    """ 
    func 函數的是處理的函數
    args 表示的引數
    callback 表示的函數處理完成後的 該執行的動作
    """
    result = func(*args)
    callback(result)
 
def add(x, y):
    return x + y
 
def print_result(result):
    print(result)
 
apply_ascyn(add, (2, 3), callback=print_result)

這裡print_result只能接收一個result的引數,不能傳入其他資訊。當想讓回撥函數存取其他變數或者特定環境的變數值的時候會遇到問題。

使用一個繫結方法來代替這個簡單函數。

def appy_async(func, args, *, callback):
    result = func(*args)
    #非同步執行的函數 同時將執行後返回到這個早從這個函數跳出去
    callback(result)
 
def add(x ,y):
    return x + y
 
class ResultHandler(object):
    def __init__(self):
        self.sequence = 0
 
    def handle(self, result):
        self.sequence += 1
        print("[{}] Got: {}".format(self.sequence, result))
 
resultHandler = ResultHandler()
appy_async(add, (2,3), callback=resultHandler.handle)

 使用閉包代替上面的類來實現

def apply_async(func, args, *, callback):
    result = func(*args)
    callback(result)
 
def add(x ,y):
    return x + y
 
def make_handler():
    sequence = 0
    def handler(result):
        nonlocal sequence
        sequence += 1
        print("[{}] Got:{}".format(sequence, result))
    return handler
 
handler = make_handler()
apply_async(add, (2,3), callback=handler)

使用協程來完成非同步操作

def apply_async(func, args, *, callback):
    result = func(*args)
    callback(result)
 
def add(x, y):
    return x + y
 
def make_handler():
    sequence = 0
    while True:
        result = yield
        sequence += 1
        print("[{}] Got:{}".format(sequence, result))
 
handle = make_handler()
next(handle)
 
apply_async(add, (2,3), callback=handle.send)

博文參考:

python3回撥函數(callback) - 知乎

總結

到此這篇關於Python中回撥函數(callback)的文章就介紹到這了,更多相關Python 回撥函數callback內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com