令人頭大的裝飾器(1)

一個(gè)筆試經(jīng)歷畜份,是一道關(guān)于裝飾器的題目玄叠,那時(shí)候的感覺(jué)應(yīng)該是這樣:

  • " 美鋁,我們是不是認(rèn)識(shí)? "

俗話說(shuō)得好:一回生二回熟。但學(xué)習(xí)裝飾器時(shí)只是了解下臼闻,同時(shí)久不使用這方面的知識(shí)鸿吆,好刀都要變鈍呀,況且自己拿的還是把破刀述呐。被刺激的不要不要的 ~

首先惩淳,遇到一個(gè)云里霧里的問(wèn)題:

1. 什么是裝飾器?

第一要明確知道的概念:裝飾器屬于Python的高階函數(shù)(聽(tīng)說(shuō)還是最常用到的高階函數(shù))乓搬。兩個(gè)重點(diǎn):

  1. 它是一個(gè)函數(shù)
  2. 它是一個(gè)感覺(jué)起來(lái)很高級(jí)的函數(shù)

所以思犁,【劃重點(diǎn)】裝飾器是一個(gè)語(yǔ)法糖,它以一個(gè)函數(shù)為參數(shù)进肯,并返回一個(gè)加強(qiáng)版的原函數(shù)(方法或者類(lèi))對(duì)象激蹲。當(dāng)然,這個(gè)裝飾器要設(shè)計(jì)正確江掩。

有點(diǎn)口語(yǔ)化学辱,那就摘抄一段正式點(diǎn)的概念:

裝飾器本質(zhì)上是一個(gè)Python函數(shù),它可以讓其他函數(shù)在不需要做任何代碼變動(dòng)的前提下增加額外功能环形,裝飾器的返回值也是一個(gè)函數(shù)對(duì)象策泣。它經(jīng)常用于有切面需求的場(chǎng)景,比如:插入日志抬吟、性能測(cè)試萨咕、事務(wù)處理、緩存拗军、權(quán)限校驗(yàn)等場(chǎng)景任洞。裝飾器是解決這類(lèi)問(wèn)題的絕佳設(shè)計(jì),有了裝飾器发侵,我們就可以抽離出大量與函數(shù)功能本身無(wú)關(guān)的雷同代碼并繼續(xù)重用交掏。

enmm~那裝飾器的作用就是

在不改動(dòng)函數(shù)的情況下,給函數(shù)或者對(duì)象(其實(shí)函數(shù)也是一個(gè)對(duì)象)在運(yùn)行時(shí)動(dòng)態(tài)地額外添加其他的功能刃鳄。

那么就進(jìn)入第二內(nèi)容盅弛,寫(xiě)一點(diǎn)代碼出來(lái)溜溜,來(lái)理解下令人無(wú)趣的概念

2. 入門(mén)級(jí)別的裝飾器(面試題就是入門(mén)級(jí)的叔锐,我好想哭)

別嗶嗶挪鹏,直接上代碼:

# 有個(gè)單純要去看電影的函數(shù),就叫 movie() 吧愉烙,但你又想邊看電影邊吃爆米花讨盒。用裝飾器如何寫(xiě)呢?

def extra(func):
    """給 movie()添加額外的功能"""
    def wrapper():
        print("我要先把爆米花和可樂(lè)買(mǎi)了步责!")
        return func()  # 得在加強(qiáng)版原函數(shù)里調(diào)用原函數(shù)返顺。給自己穿漂亮的衣服可不要把自己本身忘記了禀苦。
    return wrapper

@extra
def movie():
    print("我要看電影。")
              
movie()

-----------------------------這是運(yùn)行結(jié)果線----------------------------------------

我要先把爆米花和可樂(lè)買(mǎi)了遂鹊!
我要看電影振乏。

extra() 函數(shù)就是一個(gè)裝飾器。(兩點(diǎn)分析)

  1. 在 extra 函數(shù)中傳入的 func參數(shù)是一個(gè)函數(shù)秉扑,即 movie()這個(gè)函數(shù)慧邮。符合高階函數(shù)的身份。在以前沒(méi)有加入語(yǔ)法糖時(shí)舟陆,@extra 等價(jià)于 movie = extra( movie )误澳。這里涉及到一個(gè)知識(shí)點(diǎn):

函數(shù)是一個(gè)對(duì)象,函數(shù)對(duì)象還可以賦值給變量吨娜。所以可以通過(guò)變量調(diào)用這個(gè)函數(shù)脓匿。

def cat():
    print('This is a ugly cat!')

c = cat # 將函數(shù)對(duì)象賦值給變量c
c()        

其實(shí),Python 里所有數(shù)據(jù)——布爾值宦赠、整數(shù)陪毡、浮點(diǎn)數(shù)、字符串,甚至大型數(shù)據(jù)結(jié)構(gòu)勾扭、函數(shù)以及程序——都是以對(duì)象(object)的形式存在的毡琉。
扯遠(yuǎn)了,回歸正題——

  1. return wrapper 中的 wrapper 就是加強(qiáng)版的 movie函數(shù)妙色。這個(gè)加強(qiáng)版的movie函數(shù)除了有看電影還有了要買(mǎi)爆米花和可樂(lè)的功能桅滋。符合返回一個(gè)加強(qiáng)版的原函數(shù)的概念。

但是——
如果這個(gè)被裝飾器裝飾的函數(shù) moive需要傳入一個(gè)電影名name的參數(shù)身辨。那么這個(gè)加強(qiáng)版函數(shù)wrapper和其里面的函數(shù)func也要做相應(yīng)的更改丐谋。但 return wrapper中的wrapper不需要更改,因裝飾器返回的是一個(gè)對(duì)象煌珊。是不需要添加參數(shù)的号俐。

def extra(func):
    """給 movie()添加額外的功能"""
    def wrapper(name):   # 一毛一樣的參數(shù)
        print("我要先把爆米花和可樂(lè)買(mǎi)了!")
        return func(name)
    return wrapper

@extra
def movie(name):
    print("我要看《{}》電影定庵。".format(name))
              
movie('蜘蛛俠 英雄歸來(lái)')
----------------迷人的結(jié)果線------------------

我要先把爆米花和可樂(lè)買(mǎi)了吏饿!
我要看《蜘蛛俠 英雄歸來(lái)》電影。

雖然把裝飾器的里的加強(qiáng)版函數(shù)的參數(shù)弄的與原函數(shù)一毛一樣蔬浙,但這裝飾器是一種封裝猪落,如果萬(wàn)一你想看一部,而其他人想看兩部呢畴博?難道又給另個(gè)人寫(xiě)個(gè)相似的裝飾器嗎笨忌?所以讓裝飾器同步更改參數(shù)的做法是不可取的。好辦法就是給裝飾器一個(gè)無(wú)敵的參數(shù)俱病,一個(gè)可變參數(shù)*args和關(guān)鍵字參數(shù)**kwargs官疲。

def extra(func):
    """給 movie()添加額外的功能"""
    def wrapper(*args, **kwagrs):   # 無(wú)敵的參數(shù)了吧
        print("我要先把爆米花和可樂(lè)買(mǎi)了杂曲!")
        return func(*args, **kwagrs)
    return wrapper

@extra
def movie1(name):
    print("我要看《{}》電影。".format(name))
    
@extra
def movie2(name1, name2):
    print("我要看兩部電影《{0}》和《{1}》".format(name1, name2))
              
movie1('蜘蛛俠 英雄歸來(lái)')
print('\n')
movie2('蜘蛛俠 英雄歸來(lái)','猩球崛起')

嘻嘻袁余,好累呀!那么入門(mén)的就結(jié)束了咱揍,進(jìn)入進(jìn)階版本的裝飾器了颖榜。發(fā)車(chē)了~~~吱吱吱~~~
還是下一篇再寫(xiě)吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末煤裙,一起剝皮案震驚了整個(gè)濱河市掩完,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硼砰,老刑警劉巖且蓬,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異题翰,居然都是意外死亡恶阴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)豹障,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冯事,“玉大人,你說(shuō)我怎么就攤上這事血公£墙觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵累魔,是天一觀的道長(zhǎng)摔笤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)垦写,這世上最難降的妖魔是什么吕世? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮梯澜,結(jié)果婚禮上寞冯,老公的妹妹穿的比我還像新娘。我一直安慰自己晚伙,他們只是感情好吮龄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著咆疗,像睡著了一般漓帚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上午磁,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天尝抖,我揣著相機(jī)與錄音毡们,去河邊找鬼。 笑死昧辽,一個(gè)胖子當(dāng)著我的面吹牛衙熔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搅荞,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼红氯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了咕痛?” 一聲冷哼從身側(cè)響起痢甘,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茉贡,沒(méi)想到半個(gè)月后塞栅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腔丧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年放椰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愉粤。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庄敛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出科汗,到底是詐尸還是另有隱情藻烤,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響肝箱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兴猩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望早歇。 院中可真熱鬧倾芝,春花似錦、人聲如沸箭跳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谱姓。三九已至借尿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背路翻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工狈癞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茂契。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓蝶桶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親掉冶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子莫瞬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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