2.閉包和裝飾器

閉包:https://zhuanlan.zhihu.com/p/93846887
裝飾器:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584
https://www.cnblogs.com/yaoqingzhuan/p/10628592.html
python參考手冊(cè):相關(guān)章節(jié)

一.預(yù)備知識(shí)

1.作用域、內(nèi)嵌函數(shù)、生命周期

python中的每個(gè)函數(shù)都是一個(gè)新的作用域彤叉,或者理解為命名空間
一般而言,函數(shù)中定義的變量浮庐、內(nèi)嵌函數(shù)等贰逾,其生命周期即所在函數(shù)的作用域母廷,當(dāng)函數(shù)執(zhí)行完畢后搅轿,函數(shù)內(nèi)所定義變量富玷、內(nèi)嵌函數(shù)等都應(yīng)該會(huì)消失。而在下一次調(diào)用時(shí)雀鹃,又會(huì)被重新創(chuàng)建励两。

2.變量搜索

當(dāng)在函數(shù)中訪問(wèn)一個(gè)新的變量時(shí),python會(huì)在當(dāng)前命名空間中尋找該變量是否存在傅瞻。如果不存在則會(huì)從上一級(jí)命名空間中搜尋,直到頂層命名空間俭正。比如:


image.png

但是在函數(shù)中對(duì)一個(gè)變量進(jìn)行定義或者賦值時(shí)掸读,python只會(huì)在當(dāng)前命名空間中搜尋該變量,如果不存在儿惫,則會(huì)創(chuàng)建一個(gè)新的變量。如果上一級(jí)命名空間中存在同名的變量留搔,那么上一級(jí)同名變量會(huì)在當(dāng)前作用于中被覆蓋铛铁。


image.png

二.閉包

1.定義
將組成函數(shù)的語(yǔ)句和這些語(yǔ)句執(zhí)行環(huán)境打包在一起時(shí),得到的對(duì)象稱為閉包括眠。

2.使用場(chǎng)景
函數(shù)在python中是第一類對(duì)象倍权。也就是說(shuō)可以把他們當(dāng)作參數(shù)傳遞給其他函數(shù)放在數(shù)據(jù)結(jié)構(gòu)中当船、以及作為函數(shù)的返回結(jié)果等默辨。(這些場(chǎng)景都會(huì)觸發(fā)閉包)
把函數(shù)當(dāng)作數(shù)據(jù)處理時(shí),它將隱式地?cái)y帶與定義該函數(shù)的周圍環(huán)境相關(guān)的信息(該函數(shù)所需的所有信息)廓奕。

3.舉例說(shuō)明

  • 示例1:閉包影響自由變量的綁定方式
# foo.py
x = 42
def callf(func):
  return func()

# 調(diào)用代碼
import foo
x = 37
def helloworld():
  return "Hello world, x is %d" %x
fool.callf(helloworld)

輸出結(jié)果:
Hello world, x is 37
  • 示例2:閉包捕捉函數(shù)執(zhí)行所需的整個(gè)環(huán)境


    image.png

    從作用域的角度:foo實(shí)際上是調(diào)用了內(nèi)嵌函數(shù)inner(), 當(dāng)執(zhí)行到inner中的print(x)語(yǔ)句時(shí)桌粉,在inner()中沒(méi)有搜尋到x,然后會(huì)在outer()命名空間中搜尋患亿,找到x后進(jìn)行打印。
    從生命周期的角度步藕,foo的值為outer函數(shù)的返回值,當(dāng)執(zhí)行foo()時(shí)沾歪,outer函數(shù)已經(jīng)執(zhí)行完畢了雾消,此時(shí)其作用于內(nèi)定義的變量x也應(yīng)該已經(jīng)銷毀,因此執(zhí)行foo()時(shí)狂窑,當(dāng)執(zhí)行到print(x)時(shí)桑腮,應(yīng)該會(huì)出錯(cuò)。但實(shí)際上并沒(méi)有破讨。
    這其實(shí)是python支持函數(shù)閉包的特性。

三.裝飾器

閉包會(huì)捕捉內(nèi)部的環(huán)境信息采呐,因此還可以用于包裝現(xiàn)有函數(shù)搁骑。

1.定義

裝飾器是一個(gè)函數(shù)(也可以是類或者對(duì)象)又固,其主要用途是包裝另一個(gè)函數(shù)或者。這種包裝的首要目的是光明睜大的修改或者增強(qiáng)被包裝對(duì)象的行為乏冀。

2.分類

1.函數(shù)裝飾器

根據(jù)裝飾器本身是否接受參數(shù)洋只,可以分為:帶參數(shù)的裝飾器和不帶參數(shù)的裝飾器
A.不帶參數(shù)的裝飾器:包裝的函數(shù)func本身,作為裝飾器的入?yún)ⅰ?/p>

@trace
def square(x):
  return x*x

#其等價(jià)于:
def square(x):
  return x*x
square = trace(square)

# trace代碼的實(shí)現(xiàn)如下
# 備注:內(nèi)部函數(shù)callf作為返回值肢扯,是一個(gè)閉包
def trace(func):
  def callf(*args, **kwargs):
    debug_log.write('calling args:%s' % args)
    r = func(*args, **kwargs)
    debug_log.write('%s returned' % r)
    return r
  return callf

B.帶參數(shù)的裝飾器(多一層對(duì)裝飾器參數(shù)的處理)
首先:參數(shù)param作為裝飾器的入?yún)⒌4福祷氐谝粚雍瘮?shù):W。(第一層:對(duì)裝飾器本身參數(shù)的處理)
然后:將包裝的函數(shù)func本身肛循,作為W的入?yún)⒁瘢瑐鬟f執(zhí)行累舷。(第二層:對(duì)包裝函數(shù)的處理,不帶參數(shù)的裝飾器析孽,只有該層)

# 裝飾器帶參數(shù)的版本:
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

# 其含義是:
now = log('execute')(now)

# 裝飾器本身不帶參數(shù)的版本:
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
# 其含義是:
now = log(now)
2.使用類作為裝飾器

類也可以作為裝飾器害捕。


image.png
3.使用對(duì)象作為裝飾器

根據(jù)裝飾器的語(yǔ)法尝盼,對(duì)象也可以作為裝飾器。使用對(duì)象裝飾器有時(shí)候會(huì)更加靈活盾沫,例如能夠方便的定制和添加參數(shù)。


image.png
4.裝飾器裝飾類

接受類作為輸入佩捞,并返回類作為輸出


image.png

備注:
由此可見(jiàn)一忱,@本身是一個(gè)python的語(yǔ)法糖谭确。它只是按照固定格式進(jìn)行展開(kāi),展開(kāi)后只要符合python語(yǔ)法逐哈,不論是:類、對(duì)象禀梳、函數(shù)等肠骆,都允許靈活的搭配使用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末郊艘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纱注,更是在濱河造成了極大的恐慌,老刑警劉巖刻获,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞎嬉,死亡現(xiàn)場(chǎng)離奇詭異氧枣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)便监,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)毁靶,“玉大人逊移,你說(shuō)我怎么就攤上這事」詹妫” “怎么了扇商?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我窘拯,道長(zhǎng),這世上最難降的妖魔是什么暇番? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任思喊,我火速辦了婚禮,結(jié)果婚禮上舆乔,老公的妹妹穿的比我還像新娘。我一直安慰自己希俩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布璃搜。 她就那樣靜靜地躺著鳞上,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唾糯。 梳的紋絲不亂的頭發(fā)上涡上,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音吩愧,去河邊找鬼雁佳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糖权,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疚顷,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼禁偎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了如暖?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酗洒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后棋嘲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體箫老,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年阔籽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牲蜀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡在辆,死狀恐怖度苔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸦概,我是刑警寧澤甩骏,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站咨察,受9級(jí)特大地震影響福青,放射性物質(zhì)發(fā)生泄漏摄狱。R本人自食惡果不足惜无午,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一指厌、第九天 我趴在偏房一處隱蔽的房頂上張望踊跟。 院中可真熱鬧鸥诽,春花似錦箕憾、人聲如沸牡借。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至上真,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間根竿,已是汗流浹背就珠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壳炎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓冕广,卻偏偏與公主長(zhǎng)得像偿洁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涕滋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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

  • 在學(xué)習(xí) Python 的時(shí)候锨用,慶幸自己有 JavaScript 的基礎(chǔ),在學(xué)習(xí)過(guò)程中啄巧,發(fā)現(xiàn)許多相似的地方,如導(dǎo)包的...
    柏丘君閱讀 1,199評(píng)論 2 8
  • 導(dǎo)讀:Python中的裝飾器經(jīng)常用于有切面需求的場(chǎng)景码泛,較為經(jīng)典的有插入日志澄耍、性能測(cè)試、事務(wù)處理等齐莲。本文從閉包的概念...
    zgjx閱讀 436評(píng)論 0 3
  • 一直不理解裝飾器原理,在知乎上找到一篇詳細(xì)的講解文章星掰,原文貼了上來(lái)多望。知乎裝飾器原文鏈接 1. Python中一切皆...
    Pig_deng飼養(yǎng)員閱讀 220評(píng)論 0 0
  • 前言 裝飾器作為Python語(yǔ)言很重要的一個(gè)特性,在實(shí)際開(kāi)發(fā)中氢烘,我們都經(jīng)常用到怀偷,包括面試的時(shí)候也會(huì)拿出來(lái)問(wèn),所以想...
    BourneKing閱讀 222評(píng)論 0 0
  • 閉包的定義 將組成函數(shù)的語(yǔ)句和這些語(yǔ)句的執(zhí)行環(huán)境打包在一起時(shí)播玖,得到的對(duì)象稱為閉包我們知道函數(shù)在Python中是第一...
    So_ProbuING閱讀 251評(píng)論 0 0