裝飾器功能秩命,就是在運行原來原代碼功能基礎(chǔ)上尉共,加上些其它功能,比如:
1弃锐、引入日志
2袄友、函數(shù)執(zhí)行時間統(tǒng)計
3、執(zhí)行函數(shù)前預(yù)備處理
4霹菊、執(zhí)行函數(shù)后清理功能
5剧蚣、權(quán)限校驗等場景
6、異常的處理
7、緩存等等鸠按。
不修改原來的代碼礼搁,進(jìn)行功能的擴展。
先明白下面的代碼:
寫代碼要遵循開放封閉原則
封閉:已實現(xiàn)的功能代碼塊
開放:對擴展開發(fā)
雖然在這個原則是用的面向?qū)ο箝_發(fā)目尖,但是也適用于函數(shù)式編程馒吴,簡單來說,它規(guī)定已經(jīng)實現(xiàn)的功能代碼不允許被修改卑雁,但可以被擴展募书。
def w1(func):
def inner():
print('驗證1')
func()
return inner
@w1
def f1():
print('f1')
python解釋器就會從上到下解釋代碼,步驟如下:
def w1(func): ==>將w1函數(shù)加載到內(nèi)存.
@w1
沒錯测蹲, 從表面上看解釋器僅僅會解釋這兩句代碼莹捡,因為函數(shù)在沒有被調(diào)用之前其內(nèi)部代碼不會被執(zhí)行。
從表面上看解釋器著實會執(zhí)行這兩句扣甲,但是 @w1 這一句代碼里卻有大文章篮赢, @函數(shù)名是python的一種語法糖。
上例@w1內(nèi)部會執(zhí)行一下操作:
執(zhí)行w1函數(shù)
執(zhí)行w1函數(shù) 琉挖,并將 @w1 下面的函數(shù)作為w1函數(shù)的參數(shù)启泣,即:@w1 等價于 w1(f1) 所以,內(nèi)部就會去執(zhí)行:
def inner():
#驗證 1
#驗證 2
#驗證 3
f1() # func是參數(shù)示辈,此時 func 等于 f1
return inner# 返回的 inner寥茫,inner代表的是函數(shù),非執(zhí)行函數(shù) ,其實就是將原來的 f1 函數(shù)塞進(jìn)另外一個函數(shù)中
w1的返回值
將執(zhí)行完的w1函數(shù)返回值 賦值 給@w1下面的函數(shù)的函數(shù)名f1 即將w1的返回值再重新賦值給 f1矾麻,即:
新f1 = def inner():
#驗證 1
#驗證 2
#驗證 3
原來f1()
return inner
接下來是多個裝飾器的運用
多個裝飾器纱耻,按照從內(nèi)往外(從下往上)先后順序執(zhí)行
為了方便記憶:可以理解為先寫后運行,先寫后結(jié)束
def makeBold(fn):
print('makeBold...')
def wrapped():
return "--1--" + fn() + "--1--"
return wrapped
def makeItalic(fn):
print('makeItalic...')
def wrapped():
return "--2--" + fn() + "--2--"
return wrapped
@makeBold
def test1():
return "hello world-1"
@makeItalic
def test2():
return "hello world-2"
@makeBold
@makeItalic
def test3():
return "hello world-3"
print(test1())
print(test2())
print(test3())
運行結(jié)果如下:
makeBold...
makeItalic...
makeItalic...
makeBold...
--1--hello world-1--1--
--2--hello world-2--2--
--1----2--hello world-3--2----1--