天天看點

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

Python是一門入門容易精通難的語言,可能你花1-2個月就能入門,但是随着時間的深入,你越研究發現Python内在的内容很深,而且很複雜! Python中難的知識點很多。

今天我們來介紹一下類裝飾器,我們前面入門的文章裡面寫過一些關于裝飾器知識(2道極好的Python算法題|帶你透徹了解裝飾器的妙用),今天來介紹一下更複雜的類裝飾器.

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

我們看到很多源碼比如大名鼎鼎的Flask架構裡面經常有這樣的代碼:app = Flask(__name__)@app.route('/')defhello_world(): return'This Index Page'

代碼很簡潔,但是資訊量巨大,這是什麼鬼,根本看不懂!入門1個月内的同學基本上都看不懂,或者根本不了解這段代碼。Python學的越深,越會被這樣的問題而困擾,越想去探求Python内在的原理,這也是通往Python進階之路必修之路!

1.先來一個最最簡單的類裝飾器classHiDecorate: definfo(self,func): func()decorate=HiDecorate()@decorate.infodeff(): print ('Hi Decorate')>>Hi Decorate

HiDecorate類裡面有一個函數叫info.當我們使用類裝飾器的時候,其實就是把f當作變量傳給info裡面的func.不信我們加兩行代碼:

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

但是我們如果直接調用f()會報錯,因為info裡面沒有任何傳回的函數位址,也就是說傳回的是none,肯定會報錯!我們繼續探索。

2.函數帶參數

看懂了上面的最簡單的類裝飾之後,我們要稍微加點料了,我們給f函數加參數,如果還是按照上面的寫法肯定會報錯:因為a,b兩個參數沒有傳遞給info,這個是調用func():

一定會報“TypeError: f() missing 2 required positional arguments: 'a' and 'b'”

是以我們需要加上一個閉包來傳進來a,bclassHiDecorate: definfo(self,func): defwrap(*args): print ('func name:{},args:{}'.format(func.__name__,args)) func(*args) returnwrap decorate=HiDecorate()@decorate.infodeff(a,b): print ('Hi Decorate')f(1,2)>>funcname:f,args:(1,2)Hi Decorate

(代碼可以左右滑動看)

3.增加一些複雜度

我們把上面的稍微複雜一點,比如我們有相加add,相乘mul兩個函數,需要計算cost時間

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

>>func name:add,args:(1, 2),call_time:07/22/18 18:43:08

>>a+b=3,sleep:1.0

func name:mul,args:(1, 2),call_time:07/22/18 18:43:08

>>a+b=3,sleep:0.8

4. 最複雜的裝飾器帶參數

有的時候我們需要在裝飾器上帶參數,增加函數的功能和靈活性。比如我們在

@decorate.info()裡面帶參數來擴充功能。

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

>>format: y

format: Y

func name:f1,args:(1, 2),call_time:18-07-22

Hi Decorate

func name:f2,args:(1, 2),call_time:2018-07-22

Hi Decorate

其實就是我們需要在原來的基礎上再進行一層封裝,這樣才能把裝飾器函數後面的參數帶進去。

5.剛才的類裝飾器顯得有點臃腫,我們再次封裝來簡化

python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了
python中裝飾器_小白了解Python中類裝飾器,看這篇就夠了

總結:

這個時候,你再去看開頭Flask那段源碼,就會明白了!app = Flask(__name__)@app.route('/')defhello_world(): return'This Index Page'

類裝飾器router是調用app下面的route函數,裡面的'/',傳遞給了rule參數,而hello_world函數的位址傳遞給了decorator裡面的f參數。defroute(self, rule, **options): defdecorator(f): endpoint = options.pop('endpoint', None) self.add_url_rule(rule, endpoint, f, **options) returnf returndecorator

(代碼可以左右滑動看)

接着再decorator裡面又繼續封裝了一層去調用app類裡面的all_url_rule函數了.一層套一層,需要抽絲剝繭,慢慢的去體會!

Python是一門入門容易精通難的語言,進階之路會很慢也會很痛苦,想要翻過這座山,必須深入的研究Python内在之美,了解内在機制,經過修煉你的Python功力才會大增,才寫出一手讓人眼前一亮的code,加油吧,少年!