Python裝飾器是什麼?有什麼價值?
裝飾器就是把一個猴子,塞入煉丹爐,然後就出來一個還是會吃桃子,但有火眼金睛的猴子;還是原來的猴子,但多了特效技能。
下面我們以下4個方面介紹Python的裝飾器:
- 什麼是裝飾器?
- 為什麼Python要引入裝飾器?
- 裝飾器有利於解決哪些問題?
- 裝飾器背後的原理是什麼?
在回答以上4個問題的過程中,你會學會如何使用裝飾器
開始吧
01 什麼是裝飾器?
裝飾器可以讓一個Python函數擁有原本沒有的功能,也就是你可以通過裝飾器,讓一個平淡無奇的函數變的強大,變的漂亮。
舉幾個現實中的例子
1、你一個男的程序員,穿上女裝,戴上假髮,你就有了女人的外表(穿女裝、戴假髮的過程就是新的特效,你擁有了女人的外表,你原來的小jj還在,沒有消失)
2、你新買的毛坯房,裝修,買傢具後變好看了(裝修、傢具就是新的特效)
3、孫悟空被放進煉丹爐裝飾了一下,出來後,學會了火眼金睛,以前的本領都還在
02 為什麼Python要引入裝飾器?
因為引入裝飾器會便於開發,便於代碼復用,可以把爛泥扶上牆,
裝飾器可以讓你一秒變女人且可以保住小JJ,當你某天后悔想重新變回男人,只要脫掉女裝和假髮即可(如果你變女人的時候,給小JJ做了手術(直接修改函數體的內容),想再變回男人可就痛苦了哦)
03 裝飾器有利於解決哪些問題?
例子1:
擴展功能
比如你寫了一段代碼,當你執行 孫悟空() 就列印出它目前的技能
# python3支持用中文做函數名,# 這裡為了方便你理解,就用中文,實際情況為了兼容性,你可別用中文哦def 孫悟空(): print(吃桃子)孫悟空()# 輸出:# 吃桃子
現在你希望
孫悟空這個函數 列印出 』有火眼金睛了』,該怎麼做呢?
是的,你可以直接在函數里加一段 print(有火眼金睛了)
但是這樣會破壞原來的代碼,如果你的代碼量很多很多的話,修改起來則是災難,
不過別擔心,你還可以用裝飾器來裝飾他,讓他在原本基礎上,擴展出新的功能
代碼如下
def 煉丹爐(func): # func就是『孫悟空』這個函數 def 變身(*args, **kwargs): #*args, **kwargs就是『孫悟空』的參數列表,這裡的『孫悟空』函數沒有傳參數,我們寫上也不影響,建議都寫上 print(有火眼金睛了) # 加特效,增加新功能,比如孫悟空的進了煉丹爐後,有了火眼金睛技能 return func(*args, **kwargs) #保留原來的功能,原來孫悟空的技能,如吃桃子 return 變身 # 煉丹成功,更強大的,有了火眼金睛技能的孫悟空出世@煉丹爐def 孫悟空(): print(吃桃子)孫悟空()# 輸出:# 有火眼金睛了# 吃桃子
例子2:擴展許可權認證
比如你的代碼,默認打開就播放動畫片,代碼如下
def play(): print(開始播放動畫片 《喜洋洋和灰太狼》)play()# 輸出# 開始播放動畫片 《喜洋洋和灰太狼》
但是突然某天,你突然希望只允許1歲到10才可以看這個動畫片,不希望程序員大叔看這個動畫片怎麼辦?
是的,你可以修改這個代碼,加上年齡限制,但如果我們用裝飾器的話,就更簡單了,就可以不用破壞原來的代碼,而且方便擴展到其他函數上
userAge = 40def canYou(func): def decorator(*args, **kwargs): if userAge > 1 and userAge < 10: return func(*args, **kwargs) print(你的年齡不符合要求,不能看) return decorator@canYoudef play(): print(開始播放動畫片 《喜洋洋和灰太狼》)play()# 輸出# 你的年齡不符合要求,不能看# 你可以修改上面的 userAge 為9 試試
你看,是不是很簡單,實際情況中,很多時候,你需要對一段代碼加上許可權認證,加上各種功能;但是又不想,或者不方便破壞原有代碼,則可以用裝飾器去擴展它
04 裝飾器背後的實現原理是什麼?
原理 代碼逆推後如下
def 煉丹爐(func): def 變身(*args, **kwargs): print(有火眼金睛了) return func(*args, **kwargs) return 變身 def 孫悟空(): print(吃桃子)新_孫悟空 = 煉丹爐(孫悟空) #放入原料,原來的弱小的孫悟空,生成煉丹方案給 新_孫悟空 ,這裡也可以把煉丹方案給 原來的『孫悟空』,為了方便理解,給了新的孫悟空 新_孫悟空() # 執行煉丹程序,新的孫悟空出世
然後這段代碼,寫起來有點麻煩,Python官方出了一個快捷代碼,也就是語法糖,用了語法糖就變成了下面這樣
def 煉丹爐(func): def 變身(*args, **kwargs): print(有火眼金睛了) return func(*args, **kwargs) return 變身 @煉丹爐 # 把下面的 『孫悟空』 塞進煉丹爐,並把新的孫悟空複製給下面的函數def 孫悟空(): print(吃桃子)孫悟空() # 執行煉丹程序,新的孫悟空出世
可以一次性在一個函數上用多個裝飾器嗎?
當然可以,下面我們給孫悟空,弄個金箍棒,讓他學會72變,學會飛
def 煉丹爐(func): def 變身(*args, **kwargs): print(有火眼金睛了) return func(*args, **kwargs) return 變身def 龍宮走一趟(func): def 你好(*args, **kwargs): print(有金箍棒了) return func(*args, **kwargs) return 你好def 拜師學藝(func): def 師傅(*args, **kwargs): print(學會飛、72變了) return func(*args, **kwargs) return 師傅@拜師學藝@龍宮走一趟@煉丹爐 def 孫悟空(): print(吃桃子)孫悟空()# 輸出# 學會飛、72變了# 有金箍棒了# 有火眼金睛了# 吃桃子
上面代碼的等效於 拜師學藝(龍宮走一趟(煉丹爐(孫悟空)))
代碼的執行順序是 先從內到外
先執行 煉丹爐,然後是龍宮走一趟,最後是拜師學藝,
別搞錯了哦,建議你複製代碼到電腦上測試一下
有什麼問題,請給我留言哦
推薦閱讀: