2.3.3裝飾器與語(yǔ)法糖

總目錄:http://www.reibang.com/p/e406a9bc93a9

Python - 子目錄:http://www.reibang.com/p/50b432cb9460

裝飾器三前提:作用域、高階函數(shù)传透,閉包

作用域

?L_E_G_B

a = 10? ?

def f():

? ? a=5? ?

? ? def inner():

? ? ? ? a = 7

? ? ? ? print(a)

? ? ? ? return 1

7


高階函數(shù)

1.函數(shù)名可以作為參數(shù)輸入

2.也可以作為返回值


閉包

def outer():

? ? x = 10

? ? def inner():? ? ? #條件1:?inner就是內(nèi)部變量

? ? ? ? print(x)? ? ? ? #條件2:外部環(huán)境的一個(gè)變量

? ? return inner? ? ?#結(jié)論:內(nèi)部函數(shù)inner是一個(gè)閉包

f=outer()

f()

10


裝飾器

裝飾器本質(zhì)上是一個(gè)Python函數(shù)耘沼,它可以讓其他函數(shù)在不需要做任何代碼變動(dòng)的前提下增加額外功能,裝飾器的返回值也是一個(gè)函數(shù)對(duì)象朱盐。它經(jīng)常用于有切面需求的場(chǎng)景群嗤,比如:插入日志、性能測(cè)試兵琳、事務(wù)處理狂秘、緩存、權(quán)限校驗(yàn)等場(chǎng)景闰围。裝飾器是解決這類問題的絕佳設(shè)計(jì)赃绊,有了裝飾器,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用羡榴。

現(xiàn)在我們來舉一個(gè)例子:

假設(shè)要寫一個(gè)銀行存款取款的程序碧查,那么主干程序肯定要實(shí)現(xiàn)存款功能和取款功能:

def a():

? ? print("存款中……")

def b():

? ? print("取款中……")

button=1

if button ==1:

? ? a()

else:

? ? b()

但是除了存款功能和取款功能外,需要添加密碼驗(yàn)證功能,那么菜雞程序員肯定會(huì)添加一個(gè)新的函數(shù):

def a():

? ? print("存款中……")

def b():

? ? print("取款中……")

def c():

? ? print("密碼驗(yàn)證中……")

button=1

if button ==1:

? ? c()

? ? a()

else:

? ? c()

? ? b()

或者:

def a():

? ? c()

? ? print("存款中……")

def b():

? ? c()

? ? print("取款中……")

def c():

? ? print("密碼驗(yàn)證中……")

button=1

if button ==1:

? ? a()

else:

? ? b()

但是這兩種寫法冗余程度高忠售,都違背了開放封閉原則传惠,這只是兩個(gè)功能就要每一步都要做出修改,那么上百個(gè)功能呢稻扬?

那么我們?cè)诓桓淖冊(cè)瘮?shù)的情況下進(jìn)行修改:

def a():

? ? print("存款中……")

def b():

? ? print("取款中……")

def c(fun):

? ? print("密碼驗(yàn)證中……")

? ? fun()

button=1

if button ==1:

? ? c(a)

else:

? ? c(b)

這樣修改確實(shí)沒有修改原代碼卦方,但是程序邏輯已經(jīng)改變,如果功能多的話泰佳,都要一一修改盼砍,可維護(hù)性差。

這樣逝她,就需要我們使用裝飾器了浇坐,在不影響原程序,原邏輯黔宛,不違背開放封閉原則的情況下:

def c(func):

? ? def inner():

? ? ? ? print("密碼驗(yàn)證中……")

? ? ? ? func()

? ? return inner


def a():

? ? print("存款中……")


def b():

? ? print("取款中……")

button=1

if button ==1:

? ? a1=c(a)

? ? a1()

else:

? ? b1=c(b)

? ? b1()

這個(gè)例子只是在說明裝飾器的用途和標(biāo)準(zhǔn)用法近刘。

帶參裝飾器

現(xiàn)在讓我們擺脫這個(gè)例子,看一下帶參數(shù)的裝飾器臀晃,

def c(func):

? ? def inner():

? ? ? ? print("woshi")

? ? ? ? func()

? ? return inner


def my(a):

? ? print(a)


my1=c(my("xiaobai"))

my1()

運(yùn)行這個(gè)代碼觉渴,會(huì)報(bào)錯(cuò),原因是裝飾器的返回值是inner徽惋,而my等同于inner案淋。

現(xiàn)在我們修改一下

def c(func):

? ? def inner(*a,**b):

? ? ? ? print("woshi")

? ? ? ? func(*a,**b)

? ? return inner


def my(a):

? ? print(a)

my1=c(my("xiaobai"))

my1()

現(xiàn)在我們來看一下,裝飾器中的函數(shù)返回值:

def c(func):

? ? def inner(*a,**b):

? ? ? ? print("woshi")

? ? ? ? func(*a,**b)

? ? return inner

@c

def my1(a):

? ? return a

@c

def my2(a):

? ? print(a)


re1 = my1("111")

re2 = my2("222")

print(re1,re2)

woshi

woshi

222

None None

這是打印的結(jié)果寂曹,可以看出來兩個(gè)函數(shù)的返回值均為空哎迄,是因?yàn)椋瑹o論被裝飾的函數(shù)有無返回值隆圆,其結(jié)果都無返回值漱挚,原因其實(shí)很簡(jiǎn)單,因?yàn)閕nner()函數(shù)根本就沒有返回值渺氧。為了實(shí)現(xiàn)有返回值的函數(shù)被裝飾之后仍然有返回值旨涝,需要inner函數(shù)與被裝飾函數(shù)的返回值保持一致。

再來簡(jiǎn)單修改一下:

def c(func):

? ? def inner(*a,**b):

? ? ? ? print("woshi")

? ? ? ? re3=func(*a,**b)

? ? ? ? return re3

? ? return inner

@c

def my1(a):

? ? return a

@c

def my2(a):

? ? print(a)


re1 = my1("111")

re2 = my2("222")

print(re1,re2)

woshi

woshi

222

111 None

可以看到侣背,有返回值的函數(shù)被裝飾之后依然有返回值白华,沒有返回值的函數(shù)被裝飾之后則沒有返回值,符合我們想要的結(jié)果贩耐。


語(yǔ)法糖

上面的@c便是語(yǔ)法糖弧腥。

我們來定義一個(gè)函數(shù)

def my():

? ? print("123")

然后我們要在123上加一行=和一行*

def a(func):

? ? def inner():

? ? ? ? print('='*15)

? ? ? ? func()

? ? return inner

def b(func):

? ? def inner():

? ? ? ? print('*'*15)

? ? ? ? func()

? ? return inner

@a

@b

def my():

? ? print("123")

my()

帶參語(yǔ)法糖

但是這樣的話,函數(shù)a和函數(shù)b代碼冗余潮太,可以用帶參數(shù)的語(yǔ)法糖來優(yōu)化一下:

def a(char):

? ? def b(func):

? ? ? ? def inner():

? ? ? ? ? ? print(char*15)

? ? ? ? ? ? func()

? ? ? ? return inner

? ? return b

@a('=')

@a('*')

def my():

? ? print("123")

my()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末管搪,一起剝皮案震驚了整個(gè)濱河市虾攻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌更鲁,老刑警劉巖霎箍,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異澡为,居然都是意外死亡漂坏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門媒至,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顶别,“玉大人,你說我怎么就攤上這事塘慕〗钕模” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵图呢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我骗随,道長(zhǎng)蛤织,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任鸿染,我火速辦了婚禮指蚜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涨椒。我一直安慰自己摊鸡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布蚕冬。 她就那樣靜靜地躺著免猾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囤热。 梳的紋絲不亂的頭發(fā)上猎提,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音旁蔼,去河邊找鬼锨苏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛棺聊,可吹牛的內(nèi)容都是我干的伞租。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼限佩,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼葵诈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驯击,失蹤者是張志新(化名)和其女友劉穎烁兰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徊都,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沪斟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暇矫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主之。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖李根,靈堂內(nèi)的尸體忽然破棺而出槽奕,到底是詐尸還是另有隱情,我是刑警寧澤房轿,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布粤攒,位于F島的核電站,受9級(jí)特大地震影響囱持,放射性物質(zhì)發(fā)生泄漏夯接。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一纷妆、第九天 我趴在偏房一處隱蔽的房頂上張望盔几。 院中可真熱鬧,春花似錦掩幢、人聲如沸逊拍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)芯丧。三九已至,卻和暖如春枯怖,著一層夾襖步出監(jiān)牢的瞬間注整,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工度硝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿轨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓蕊程,卻偏偏與公主長(zhǎng)得像椒袍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藻茂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • 裝飾器本質(zhì)上是一個(gè)函數(shù)驹暑,該函數(shù)用來處理其他函數(shù)玫恳,它可以讓其他函數(shù)在不需要修改代碼的前提下增加額外的功能,裝飾器的返...
    胡一巴閱讀 418評(píng)論 0 0
  • 寫在前面的話 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,771評(píng)論 0 8
  • http://blog.csdn.net/ablo_zhou/article/details/5471952 Py...
    王江濤_6000閱讀 331評(píng)論 0 1
  • 閉包和裝飾器 閉包 定義:在函數(shù)嵌套的前提下优俘,內(nèi)部函數(shù)使用了外部函數(shù)的變量京办,并且外部函數(shù)返回了內(nèi)部函數(shù),我們把這個(gè)...
    一只學(xué)不會(huì)編程的汪汪閱讀 346評(píng)論 0 0
  • 一帆焕,老師問全班同學(xué):“小明有三個(gè)兒子惭婿,大兒子叫小日,二兒子叫小月叶雹,那么他第三個(gè)兒子叫什么”财饥?這時(shí)王小明突然站起來回...
    金字塔頂閱讀 271評(píng)論 0 2