Python裝飾器(4)帶參數(shù)的裝飾器

內(nèi)容純屬個人理解奈揍,不對之處曲尸,歡迎指正。

之前說過男翰,裝飾器其實就是函數(shù)另患,既然是函數(shù),那就可以有參數(shù)蛾绎,裝飾器也不例外昆箕,接下來我們來分析帶參數(shù)的裝飾器。

如何構(gòu)造帶參數(shù)

帶參數(shù)倒是很簡單租冠,在裝飾的時候給裝飾函數(shù)寫上參數(shù)就行鹏倘,但是具體的裝飾器函數(shù)該怎么寫,我們需要思考一下顽爹。
我們想讓它帶參數(shù)纤泵,無非就是對被裝飾函數(shù)的執(zhí)行進行一定條件的限定設(shè)置,也就是說在函數(shù)執(zhí)行之前镜粤,函數(shù)就必須具備這個條件捏题,那么這樣的話,就有兩種選擇肉渴,要么在傳遞func以后傳遞參數(shù)公荧;要么在傳遞func之前傳遞參數(shù)。
在想法上同规,兩種其實是都可以的循狰,但是窟社,我們傳遞參數(shù)的時候是給裝飾器傳遞,也就是說绪钥,裝飾器函數(shù)首先接收的是裝飾器函數(shù)的參數(shù)焰枢,然后帶著這個參數(shù)再去裝飾函數(shù)瓶颠。因此答倡,我們就必須先處理裝飾器函數(shù)的參數(shù)焕数,然后再去處理被裝飾的函數(shù)。
所以在實現(xiàn)上跪楞,我們應(yīng)該這樣去構(gòu)造帶參裝飾器函數(shù):

def deco_para(parameter):
    def deco_func(func):
        def wrapper(*args, **kwargs):
            print(parameter)
            func(*args, **kwargs)
        return wrapper
    return deco_func

帶參裝飾器示例

def deco_para(parameter):
    print('enter deco_para')

    def deco_func(func):
        print('enter deco_func')

        def wrapper(*args, **kwargs):
            print('enter wrapper')
            print(parameter)
            print('---wrapper: before func---')
            func(*args, **kwargs)
            print('---wrapper: after func---')

        return wrapper

    return deco_func


@deco_para(123)
def foo():
    print('---foo---')


if __name__ == '__main__':
    print('--start--')
    foo()

運行結(jié)果:

enter deco_para
enter deco_func
--start--
enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---

結(jié)果應(yīng)該不用多說缀去,先接收參數(shù)123,然后接收函數(shù)foo甸祭,最后執(zhí)行wrapper缕碎。

裝飾過程解析--多次輸出問題

我們解析下過程

deco_func = deco_para(123)  # 接收參數(shù)123
wrapper = deco_func(foo)  # 接收函數(shù)foo
foo = wrapper  # 重命名
foo()  # 執(zhí)行foo

如果你試著按這個過程去執(zhí)行代碼,會發(fā)現(xiàn)一個問題池户,wrapper函數(shù)里面的代碼執(zhí)行了2次咏雌。

enter deco_para
enter deco_func
enter deco_para
enter deco_func
enter wrapper
123
---wrapper: before func---
enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---
---wrapper: after func---

我們看下究竟是怎么回事。

# 程序執(zhí)行校焦,掃面到裝飾器赊抖,執(zhí)行裝飾器函數(shù)內(nèi)部代碼
1.enter deco_para
2.enter deco_func

# deco_para(123)接收參數(shù)123時執(zhí)行3
3.enter deco_para

# deco_func(foo)接收函數(shù)foo時執(zhí)行4
4.enter deco_func

# foo()執(zhí)行foo()
5.enter wrapper
6.123
7.---wrapper: before func---

8.enter wrapper
9.123
10.---wrapper: before func---
11.---foo---
12.---wrapper: after func---

13.---wrapper: after func---

在之前解析裝飾器的時候就提到過,函數(shù)被裝飾以后寨典,就不是原來的函數(shù)了氛雪,也就是說上面所執(zhí)行的foo,其實是wrapper耸成。
那么wrapper里面有什么東西呢报亩?

print('enter wrapper')
print(parameter)
print('---wrapper: before func---')
func(*args, **kwargs)
print('---wrapper: after func---')

似乎執(zhí)行結(jié)果應(yīng)該是

enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---

但是事實上,此時的wrapper里面的func已經(jīng)不是原來的func井氢。
回顧閉包:引用了自由變量的函數(shù)即是一個閉包弦追,這個被引用的自由變量和這個函數(shù)一同存在, 即使已經(jīng)離開了了創(chuàng)造它的環(huán)境也不例外
那么可以推測花竞,此時的被裝飾函數(shù)應(yīng)該具有了額外的東西劲件,這些東西就是

print('enter wrapper')
print(parameter)
print('---wrapper: before func---')
print('---wrapper: after func---')

由此也就可以知道為什么wrapper里面的代碼執(zhí)行了2次:就是在執(zhí)行到func(*args, **kwargs)的時候,執(zhí)行了功能豐富以后的func约急。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寇仓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子烤宙,更是在濱河造成了極大的恐慌,老刑警劉巖俭嘁,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躺枕,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機拐云,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門罢猪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叉瘩,你說我怎么就攤上這事膳帕。” “怎么了薇缅?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵危彩,是天一觀的道長。 經(jīng)常有香客問我泳桦,道長汤徽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任灸撰,我火速辦了婚禮谒府,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浮毯。我一直安慰自己完疫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布债蓝。 她就那樣靜靜地躺著壳鹤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惦蚊。 梳的紋絲不亂的頭發(fā)上器虾,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音蹦锋,去河邊找鬼兆沙。 笑死,一個胖子當(dāng)著我的面吹牛莉掂,可吹牛的內(nèi)容都是我干的葛圃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼憎妙,長吁一口氣:“原來是場噩夢啊……” “哼库正!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厘唾,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤褥符,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抚垃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喷楣,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡趟大,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了铣焊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逊朽。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖曲伊,靈堂內(nèi)的尸體忽然破棺而出叽讳,到底是詐尸還是另有隱情,我是刑警寧澤坟募,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布岛蚤,位于F島的核電站,受9級特大地震影響婿屹,放射性物質(zhì)發(fā)生泄漏灭美。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一昂利、第九天 我趴在偏房一處隱蔽的房頂上張望届腐。 院中可真熱鬧,春花似錦蜂奸、人聲如沸犁苏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽围详。三九已至,卻和暖如春祖屏,著一層夾襖步出監(jiān)牢的瞬間助赞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工袁勺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雹食,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓期丰,卻偏偏與公主長得像群叶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钝荡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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

  • 包(lib)街立、模塊(module) 在Python中,存在包和模塊兩個常見概念埠通。 模塊:編寫Python代碼的py...
    清清子衿木子水心閱讀 3,801評論 0 27
  • 每個人都有的內(nèi)褲主要功能是用來遮羞赎离,但是到了冬天它沒法為我們防風(fēng)御寒,咋辦端辱?我們想到的一個辦法就是把內(nèi)褲改造一下梁剔,...
    chen_000閱讀 1,360評論 0 3
  • 陸焉識與馮婉喻的故事看完了圾浅。我的心有著微微刺痛感。 一份愛情憾朴,等到滿頭白發(fā),等到痛徹心扉喷鸽,才發(fā)現(xiàn)众雷,這,原來就是愛做祝。...
    yayajy閱讀 190評論 0 0
  • 今天是個好日子
    薇薇攝影閱讀 193評論 0 0
  • 處理結(jié)果 mysql_fetch_assoc( ) 返回關(guān)聯(lián)數(shù)組 mysql_fetch_row( ) 返回索...
    FKTX閱讀 578評論 0 0