簡單瞭解Python裝飾器實現原理
有過開發經驗得朋友隊裝飾模式這個詞應該不陌生,裝飾裝飾,顧名思義就是指對我們原來有得東西進行裝飾,比如我們買了新房,那麼我們對毛坯房的裝修,就是對我們房子進行拓展,讓它更加完善!同樣得對於程式碼也是如此,我們就是對我們原有的功能進行功能的拓展!
一、假設我們有下面的一個場景
1、假設你現在是某個公司的工程師,你當前負責得事情就是公司某個專案整個系統架構基本功能得開發,後續會有很多同事會直接呼叫你寫得功能函式。於是你就風風火火得一頓狂擼,終於有了下面程式碼:def test1(): print("====給員工加薪了!====") def test2(): print("====出新版本,殺一個程式設計師祭天!====")
很好,同事們調得很舒服,系統跑得很好,老闆賺錢。。。
2、某一天,老闆突然來找你,說有個員工莫名奇妙被加薪了,並不是老闆自己加的,老闆說,加薪這裡要驗證下,只有我才有許可權給員工加薪。又說最近程式設計師急劇減少,被殺得太多了,也要加許可權,只有老闆才能殺!3、作為一個出色得程式設計師,這點要求當然沒問題,於是你又一頓加班加點狂改,把老闆的需求都是實現了,於是又有了下面的程式碼:def test1(): if ROLE == "boss": print("====給員工加薪了!====") else: print("====不好意思,您不是老闆====") def test2(): if ROLE == "boss": print("====出新版本,殺一個程式設計師祭天!====") else: print("====不好意思,您不是老闆====")
4、這一切看起來很正常,但是我們不妨假設下,如果有10000個類似得功能函式需要新增類似得驗證、又或者新增其它的功能呢?我們姑且假設你單身多年得手速非常快,但是這樣搞法也是很浪費時間的吧?更何況貿然得去改動原來得程式碼,風險也是不小的,所以我們換下面這種方式看看!
二、閉包得引入
1、之前我已經分享過閉包的學習筆記了,不瞭解的可以去看下,閉包得幾個條件如下:一個函式內定義了內函式,並且內涵是使用了外函式的區域性變數,最後外函式返回了內涵的引用。滿足了這三個條件我們就可以稱之為閉包。
2、那麼我們到底引入閉包做什麼呢?閉包又是如何解決我們上面的問題得呢?我們先看下下面這段程式碼:
def iwapper(fun): inner(): if ROLE == "boss": print("====身法驗證通過====") fun() else: print("====不好意思,您不是老闆====") return inner def test1(): print("====給員工加薪了!====") def test2(): print("====出新版本,殺一個程式設計師祭天!====") #呼叫iwapper,並傳入test1函式的引用,給員工加薪 addMoney = iwapper(test1) addMoney () #呼叫iwapper,並傳入test2函式的引用,殺程式設計師 killDev = iwapper(test2) killDev()
列印下結果:
此時,我們產生了兩個新函式,一個是addMoney(),另一個是killDev(),呼叫這兩個即實現了新增驗證得功能,保持了原來功能函式不用修改,並且大大減少了程式碼得冗餘,但是另一個問題又來了,程式碼得呼叫方式變了,我們需要告知其他所有人,修改他們得程式碼!很顯然這是一個更糟糕得做法!
3、路總是一步步走出來得,經歷了那麼多波折,真相也越來越接近了,聰明得你很快又拿出了下面得方案:
def iwapper(fun):
inner():
if ROLE == "boss":
print("====身法驗證通過====")
fun()
else:
print("====不好意思,您不是老闆====")
return inner
def test1():
print("====給員工加薪了!====")
def test2():
print("====出新版本,殺一個程式設計師祭天!====")
#呼叫iwapper,並傳如test1函式的引用,給員工加薪
test1 = iwapper(test1)
test ()
#呼叫iwapper,並傳如test2函式的引用,殺程式設計師
test2 = iwapper(test2)
test2()
列印下結果:
三、裝飾器
1、說了那麼多,我們來看看如果遇到上面的需求,如果使用Python裝飾器來實現的話會怎麼樣?看下面程式碼:
def iwapper(fun):
inner():
if ROLE == "boss":
print("====身法驗證通過====")
fun()
else:
print("====不好意思,您不是老闆====")
return inner
@iwapper
def test1():
print("====給員工加薪了!====")
@iwapper
def test2():
print("====出新版本,殺一個程式設計師祭天!====")
那麼看下效果:
很明顯,效果實現了,這時候也許就又朋友要說道說道了,nmmp,Python解析器那麼簡單,你前面說那麼多廢話幹嘛,直接一開始就來這段不就行了?朋友莫激動,先把刀放下,其實如果我們單看最後面的程式碼,我們僅僅知道@iwapper是python裝飾器的實現方式而已,但是我們並不知道這句程式碼到底幹了什麼事,而我們前面說的就是python解析器的實現原理了!其中得思想獲取會對我們有所幫助也不一定呢!
總結:這裡僅僅是對Python中裝飾器得最簡單使用方式進行學習,更重要得是學習Python決絕類似問題的思想!其更多用法大家可以查閱相關得資料,比如說帶引數的裝飾器,多個裝飾器一起使用等等!