閉包(保存變量) --在回調(diào)函數(shù)中攜帶額外狀態(tài)的幾種方法

問題: 希望編寫回調(diào)函數(shù)可以攜帶額外的狀態(tài)以便在回調(diào)函數(shù)內(nèi)部使用

首先定義一個回調(diào)函數(shù):

def apply_async(func, args, *, callback):
    result = func(*args)

    callback(result)

使用示例:

def print_reqult(result):
    """ 僅接受一個單獨的函數(shù) """
    print('Got:', result)

def add(x, y):
    return x + y

apply_async(add, (1, 2), callback=print_reqult)

Got: 3

有些時候我們希望回調(diào)函數(shù)可以同其他變量或者部分環(huán)境進行交互迟螺。

解決方案:一種在回調(diào)函數(shù)中攜帶額外信息的方法是使用綁定方法而不是普通的函數(shù)

方案1:比如柔滔,下面這個類保存了一個內(nèi)部序列號碼,每當(dāng)接收到一個結(jié)果時就遞增這個號碼

class ResultHanlder:
    def __init__(self):
        self.sequence = 0

    def handler(self, result):
        self.sequence +=1
        print('[{}] Got: {}'.format(self.sequence, result))

r = ResultHanlder()
apply_async(add, (1, 2), callback=r.handler)

[1] Got: 3

方案2:作為類的替代方案,也可以使用閉包來捕獲狀態(tài)

def make_result():
    sequence = 0
    def hanlder(result):
        nonlocal sequence
        sequence += 1
        print('[{}] Got: {}'.format(sequence, result))
    return hanlder

hanlder = make_result()
apply_async(add, (1, 2), callback=hanlder)

[1] Got: 3

方案3:有時候可以利用協(xié)程(coroutine)來完成同樣的任務(wù)

def make_result():
    sequence = 0
    while True:
        result = yield
        sequence += 1
        print('[{}] Got: {}'.format(sequence, result))

# 對于協(xié)程來說李剖,可以使用它的send()方法來作為回調(diào)函數(shù)
hanlder = make_result()
next(hanlder)  # 在使用協(xié)程前需要對其調(diào)用一次next()
apply_async(add, (1, 2), callback=hanlder.send)

[1] Got: 3

方案4:也可以通過額外的參數(shù)在回調(diào)函數(shù)中攜帶狀態(tài),然后使用partial()來處理參數(shù)個數(shù)的問題

class SequenceNo:
    def __init__(self):
        self.sequence = 0

def hanlder(result, seq):
    seq.sequence += 1
    print('[{}] Got: {}'.format(seq.sequence, result))

seq = SequenceNo()
from functools import partial
apply_async(add, (1, 2), callback=partial(hanlder, seq=seq))

[1] Got: 3

方案5:使用lambda表達式來實現(xiàn)上述相同的功能

apply_async(add, (1, 2), callback=lambda r: hanlder(r, seq))

[2] Got: 3
總結(jié):

1、主要有兩種方法可用于捕獲和攜帶狀態(tài):

  • 在類實例上攜帶狀態(tài)(將狀態(tài)附加到綁定方法上)玻侥;
  • 在閉包中攜帶狀態(tài);

2亿蒸、如果使用閉包凑兰,那么需要對可變變量多加留意。nonlocal聲明用來表示變量sequence是在回調(diào)函數(shù)中修改的边锁;

3姑食、使用協(xié)程的好處:

  • 更加清晰;
  • 變量可以自由的修改茅坛,不必?fù)?dān)心nonlocal聲明音半;
  • 在使用協(xié)程前需要先對其調(diào)用一次next()。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市曹鸠,隨后出現(xiàn)的幾起案子煌茬,更是在濱河造成了極大的恐慌,老刑警劉巖物延,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宣旱,死亡現(xiàn)場離奇詭異,居然都是意外死亡叛薯,警方通過查閱死者的電腦和手機浑吟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耗溜,“玉大人组力,你說我怎么就攤上這事《端” “怎么了燎字?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阿宅。 經(jīng)常有香客問我候衍,道長,這世上最難降的妖魔是什么洒放? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任蛉鹿,我火速辦了婚禮,結(jié)果婚禮上往湿,老公的妹妹穿的比我還像新娘妖异。我一直安慰自己,他們只是感情好领追,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布他膳。 她就那樣靜靜地躺著,像睡著了一般绒窑。 火紅的嫁衣襯著肌膚如雪棕孙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天些膨,我揣著相機與錄音散罕,去河邊找鬼。 笑死傀蓉,一個胖子當(dāng)著我的面吹牛欧漱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播葬燎,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼误甚,長吁一口氣:“原來是場噩夢啊……” “哼缚甩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窑邦,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤擅威,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后冈钦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體郊丛,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年瞧筛,在試婚紗的時候發(fā)現(xiàn)自己被綠了厉熟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡较幌,死狀恐怖揍瑟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乍炉,我是刑警寧澤绢片,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站岛琼,受9級特大地震影響底循,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜槐瑞,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一此叠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧随珠,春花似錦、人聲如沸猬错。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倦炒。三九已至显沈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逢唤,已是汗流浹背拉讯。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鳖藕,地道東北人魔慷。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像著恩,于是被迫代替她去往敵國和親院尔。 傳聞我的和親對象是個殘疾皇子蜻展,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin 邀摆,快速學(xué)習(xí)Kotlin纵顾! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,146評論 9 118
  • 當(dāng)圖片中的內(nèi)容較多栋盹,相互遮蓋時施逾,我們可以通過設(shè)置相關(guān)內(nèi)容的透明度來使圖片更易于觀察,也即是通過本節(jié)中的bbox參數(shù)...
    Ledestin閱讀 344評論 0 0
  • 母親打電話跟我說前幾天回老家了例获。 去年夏天的洪水沖壞了回去的那條窄到僅可通過一輛車的柏油路汉额,公共汽車也停運了,她與...
    語見1992閱讀 507評論 0 5
  • 文/哥倫比亞的倒影 當(dāng)一件事被列入生活日程躏敢,突然中斷它會帶來不安闷愤。 在忙碌中總惦記著未履行的習(xí)慣,即使它被一推再推...
    哥倫比亞的倒影閱讀 293評論 3 0