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

摘要

主要是介紹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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: