Python裝飾器是什麼?有什麼價值?

裝飾器就是把一個猴子,塞入煉丹爐,然後就出來一個還是會吃桃子,但有火眼金睛的猴子;還是原來的猴子,但多了特效技能。

下面我們以下4個方面介紹Python的裝飾器:

  1. 什麼是裝飾器?
  2. 為什麼Python要引入裝飾器?
  3. 裝飾器有利於解決哪些問題?
  4. 裝飾器背後的原理是什麼?

在回答以上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變了# 有金箍棒了# 有火眼金睛了# 吃桃子

上面代碼的等效於 拜師學藝(龍宮走一趟(煉丹爐(孫悟空)))

代碼的執行順序是 先從內到外

先執行 煉丹爐,然後是龍宮走一趟,最後是拜師學藝,

別搞錯了哦,建議你複製代碼到電腦上測試一下

有什麼問題,請給我留言哦


推薦閱讀:

TAG:Python | Python入門 | 裝飾器 |