Python成长之路_装饰器
一、初入裝飾器
1、首先呢我們有這么一段代碼,這段代碼假設(shè)是N個業(yè)務(wù)部門的函數(shù) 1 def f1(aaa): 2 print('我是F1業(yè)務(wù)') 3 if aaa == 'f1': 4 return 'ok' 5 6 def f2(aaa): 7 print('我是F2業(yè)務(wù)') 8 if aaa == 'f2': 9 return 'ok' 業(yè)務(wù)代碼這里的函數(shù)的意思就是當(dāng)我們調(diào)用上面的函數(shù)的時候,傳入值給aaa,當(dāng)aaa的值等于f1或者f2就返回ok
2、公司有N個業(yè)務(wù)部門,1個基礎(chǔ)平臺部門,基礎(chǔ)平臺負(fù)責(zé)提供底層的功能,如:數(shù)據(jù)庫操作、redis調(diào)用、監(jiān)控API等功能。業(yè)務(wù)部門使用基礎(chǔ)功能時,只需調(diào)用基礎(chǔ)平臺提供的功能即可。那么我們業(yè)務(wù)部門調(diào)用功能的時候只需要。
f1(值)
f2(值)
3、公司的運(yùn)行正在有條不穩(wěn)的進(jìn)行,然而有一天呢,你的老大說,我發(fā)現(xiàn)了一個問題就是呢業(yè)務(wù)部調(diào)用基礎(chǔ)平臺的功能的時候沒有驗(yàn)證這樣不好所以呢老大就把工作交給了LOW們,要求增加驗(yàn)證功能并且業(yè)務(wù)部門在調(diào)用功能的方式不能變
Low A,這個A呢他是這么做的
他呢跟各個做基礎(chǔ)功能的人協(xié)調(diào),要求在自己的代碼上加入驗(yàn)證模塊,那么這樣呢整個的基礎(chǔ)平臺就不需要更改,結(jié)果,Low A當(dāng)天就被開除了……
Low B,這個B呢一看A都被開除了不行上面的方法不行哪就換一個
1 def f1(aaa): 2 #驗(yàn)證代碼 3 #驗(yàn)證代碼 4 print('我是F1業(yè)務(wù)') 5 if aaa == 'f1': 6 return 'ok' 7 8 def f2(aaa): 9 #驗(yàn)證代碼 10 #驗(yàn)證代碼 11 print('我是F2業(yè)務(wù)') 12 if aaa == 'f2': 13 return 'ok' LowB?
這家伙呢在每個功能前面加入了驗(yàn)證代碼,然后過了兩天Low B也被開除了
最后老大把工作交給了Low C
Low C呢總結(jié)了兩個Low的教訓(xùn)他是這么干的
1 #驗(yàn)證函數(shù) 2 def verify(): 3 # 驗(yàn)證1 4 # 驗(yàn)證2 5 # 驗(yàn)證3 6 pass 7 8 def f1(aaa): 9 verify(): 10 print('我是F1業(yè)務(wù)') 11 if aaa == 'f1': 12 return 'ok' 13 14 def f2(aaa): 15 verify(): 16 print('我是F2業(yè)務(wù)') 17 if aaa == 'f2': 18 return 'ok' Lowc?
他呢把驗(yàn)證功能的,寫成了一個函數(shù)然后,每個業(yè)務(wù)模塊來去調(diào)用 老大看見了LowC的實(shí)現(xiàn)方式,嘴角露出了一絲微笑,并且與LowC聊了個天 ? 老大說:寫代碼要遵循開發(fā)封閉原則,雖然在這個原則是用的面向?qū)ο箝_發(fā),但是也適用于函數(shù)式編程,簡單來說,它規(guī)定已經(jīng)實(shí)現(xiàn)的功能代碼不允許被修改,但可以被擴(kuò)展,即:
- 封閉:已實(shí)現(xiàn)的功能代碼塊
- 開放:對擴(kuò)展開發(fā)
如果將開放封閉原則應(yīng)用在上述需求中,那么就不允許在函數(shù) f1 、f2的內(nèi)部進(jìn)行修改代碼,老板就給了Low C一個實(shí)現(xiàn)方案:
裝飾器(單層裝飾器)
1 def out(main): 2 def wra(): 3 # 驗(yàn)證1 4 # 驗(yàn)證2 5 # 驗(yàn)證3 6 return xxx 7 return wra 8 9 @out 10 def f1(aaa): 11 print('我是F1業(yè)務(wù)') 12 if aaa == 'f1': 13 return 'ok' 14 15 @out 16 def f2(aaa): 17 print('我是F2業(yè)務(wù)') 18 if aaa == 'f2': 19 return 'ok' 單層裝飾器?
二、好,故事(這個故事是盜取銀角大王的)到此結(jié)束我們開始來看上面的代碼
(1)首先我們要知道當(dāng)函數(shù)不加括號我們的函數(shù)是不被執(zhí)行的,它會返回這個函數(shù)的內(nèi)存地址 1 def aaa(): 2 print("ok") 3 4 print(aaa) 5 6 <function aaa at 0x0000000000B6AC80> 函數(shù)內(nèi)存地址(2)然后我們來解釋一下@out
@out就等于f1 = out(f1)
什么意思呢@out是python語法中的一個簡寫,他的用處就是針對裝飾器來去做的,我們看下面的例子,將@out替換成
f1 = out(f1) 1 def out(main): 2 def wra(aaa): 3 print('我進(jìn)來了') 4 ccc = main(aaa) 5 return ccc 6 return wra 7 8 def f1(aaa): 9 print('我是F1業(yè)務(wù)') 10 if aaa == 'f1': 11 return 'ok' 12 13 f1 = out(f1) 14 15 s1 = 'f1' 16 17 ff1 = f1(s1) 18 print(ff1) 轉(zhuǎn)換后 (3)我們來解釋下out函數(shù),對于out來說他首先接收一個值,從上面可以看出他接收的值是f1,f2的內(nèi)存地址,然后return返回函數(shù)wra,注意的是f1 = out(f1),沒加括號所以都沒執(zhí)行,返回wra的時候也沒加括號所以也沒執(zhí)行,那么到了這里這個函數(shù)就先暫停我們結(jié)合者調(diào)用來看下面的圖: 第一步:請務(wù)必分開wra不等于f1而是main等于f1!!下面的f1就等于wra的意思是執(zhí)行f1函數(shù)就等于執(zhí)行wra函數(shù) 第二步: 最后呢我們通過python語法塘,將f1 = out(f1) 變成@out就變成了之前我們看到的代碼 1 def out(main): 2 def wra(aaa): 3 print('我進(jìn)來了') 4 ccc = main(aaa) 5 return ccc 6 return wra 7 8 @out 9 def f1(aaa): 10 print('我是F1業(yè)務(wù)') 11 if aaa == 'f1': 12 return 'ok' 13 14 15 s1 = 'f1' 16 ff1 = f1(s1) 17 print(ff1) 完整單層裝飾器 友情提示: 在此請將之前的練習(xí)一下并且熟知其中的原理再進(jìn)行下面的學(xué)習(xí),大神除外 (4)裝飾器裝上含有參數(shù)的函數(shù),有同學(xué)可能測試了一下說,我把函數(shù)f1的參數(shù)變成了多個,裝飾器就報(bào)錯了,那是怎么回事呢,原因很簡單,因?yàn)閣ra首先他只能接收一個參數(shù),并且ccc = main(aaa)也只接收了一個參數(shù) 1 def out(main): 2 def wra(aaa): 3 print('我進(jìn)來了') 4 ccc = main(aaa) 5 return ccc 6 return wra 單參數(shù)?
既然知道了原因那么我們就給他改改數(shù)碼寶貝超進(jìn)化…:
1 def out(main): #這里就不多解釋了跟上面一樣 2 def wra(*aaa,**aa): #這里呢變成了啥是不是可以接收各種的參數(shù)了 3 print('我進(jìn)來了') 4 ccc = main(*aaa,**aa) #這里呢也可以給f1各種參數(shù) 5 return ccc 6 return wra 7 8 @out 9 def f1(*af1): 10 print('我是F1業(yè)務(wù)') 11 print(af1[0]) #給大家測試用的 12 print(af1[1]) 13 if af1[0] == 'f1': 14 return 'ok' 15 16 s1 = 'f1' 17 ff1 = f1(s1,'我是參數(shù)2') #傳入了兩個值s1和我是參數(shù)2' 18 print(ff1) #運(yùn)行一下看看吧呵呵 裝飾參數(shù)函數(shù)的裝飾器三、裝飾器的終極進(jìn)化(多層裝飾器)邏輯比較繞
有一天,變態(tài)的老大又找到了Low C說你的裝飾器練習(xí)的咋樣了,Low C說:經(jīng)過老大的調(diào)教,我已經(jīng)練習(xí)的差不多了,這個時候老大陰陰的呵呵一笑,好,這樣我呢又有個需求要你給我改改,我現(xiàn)在呢想在驗(yàn)證之后呢添加一個歡迎功能,這個功能呢,我們業(yè)務(wù)線的功能想要添加就添加先要不添加就不添加,要記住封閉原則哦0.0……….
第二天Low C找到了老大說,大哥啊您晚上還是來我家教教我吧,真心的不知道啊0.0,,,于是老大就去了Low C的家里經(jīng)過一場風(fēng)云(此次省略一萬個字)0.0老大提供了另外的參考代碼:
1 def ds(): 2 print('ok我是歡迎信息1') 3 4 def ss(): 5 print('ok我是歡迎信息2') 6 7 8 def fill(*ill): 9 def out(main): 10 def wra(*waa,**wad): 11 ill[0]() 12 ill[1]() 13 ccc = main(waa[0]) 14 return ccc 15 return wra 16 return out 17 18 19 @fill(ds,ss) 20 def f1(aaa): 21 print('我是F1業(yè)務(wù)') 22 if aaa == 'f1': 23 return 'ok' 24 25 26 c1 = f1('f1') 27 print(c1) 老大的代碼?
哈哈看不懂了吧(大神除外)來吧我們分開來看就知道了 第一步:還是先解釋一下裝飾器fill請看圖片,有一句話要牢記這個裝飾器我就把它理解成調(diào)用,也就是把需要用的函數(shù)傳入到裝飾器做值,從而調(diào)用值來執(zhí)行函數(shù) ? 第二步:?
好到了這里大家應(yīng)該明白了吧,不明白的留言,講錯了的請指教謝謝O(∩_∩)O~~,那么有的小伙伴要問了,這尼瑪不對啊,為毛我把@fill(ds,ss)變成@fill(ss)就報(bào)錯了呢?
我們分析一下問題,主要的原因呢就是def wra函數(shù)下面執(zhí)行了 ill[1]報(bào)錯了,因?yàn)檫@里*ill只有一個參數(shù)那么避免呢,看我的終極大招:
1 def ds(): 2 print('ok我是歡迎信息1') 3 def ss(): 4 print('ok我是歡迎信息2') 5 6 def fill(*ill): 7 def out(main): 8 def wra(*waa,**wad):#這里加個判斷不就完了么 O(∩_∩)O哈哈~ 9 if len(ill) != '0': 10 for i in range(0,len(ill)): 11 ill[i]() 12 ccc = main(waa[0]) 13 return ccc 14 return wra 15 return out 16 17 @fill(ss,ds) 18 def f1(aaa): 19 print('我是F1業(yè)務(wù)') 20 if aaa == 'f1': 21 return 'ok' 22 23 @fill() #你看這里沒參數(shù)吧 24 def f2(aaa): 25 print('我是F2業(yè)務(wù)') 26 if aaa == 'f2': 27 return 'ok' 28 29 c1 = f1('f1') 30 print(c1) 31 c2 = f2('f2') 32 print(c2) 終極大招-多層裝飾器?
#運(yùn)行下試試吧 等等!最后老大和Low C成為了…此處省略一百萬個字 作者:北京小遠(yuǎn)
出處:http://www.cnblogs.com/bj-xy/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
轉(zhuǎn)載于:https://www.cnblogs.com/bj-xy/p/5185306.html
總結(jié)
以上是生活随笔為你收集整理的Python成长之路_装饰器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: class之cls
- 下一篇: Android实例-手机安全卫士(三十六