python中的裝飾器的使用實戰
1、裝飾器的理解
裝飾器是將一個函式鑲嵌在另一個函式中進行重複使用的目的,不改變其結構,增加函式的使用方式,但是不用寫過多冗餘的程式碼;
裝飾器本質上是一個Python函式,它可以讓其他函式在不需要做任何程式碼變動的前提下增加額外功能,裝飾器的返回值也是一個函式物件。
通常用到的功能:1.引入日誌;2.函式執行時間統計;3.執行函式前預備處理;4.執行函式後清理功能;5.許可權校驗;6.快取
2、實現原理與通用寫法
我們們可以從一個簡單的記錄函式執行時間的簡單裝飾器,舉一反三,推匯出一個通用的裝飾器寫法
import time def timer(func): ''' 記錄方法執行時間的裝飾器 :param func: 方法 :return:函式物件 ''' def deco(*args, **kwargs): startTime = time.time() f = func(*args, **kwargs) endTime = time.time() msecs = (endTime - startTime) * 1000 print("time is %d ms" % msecs) return f # 如果 func 有返回值得話,需要在此return回去,否則,預設返回值為 None,一般預設都返回 return deco @timer def test(parameter): print("test is running!") time.sleep(1) return "Returned value" # 該函式有返回值,所以需要在 裝飾器中的 deco 方法中 寫返回值 t = test('aa') print(t)
這是一個很簡單的通用的記錄時間的裝飾器,從而推匯出一個通用的裝飾器寫法:
def func_name(func): # 自定義裝飾器函式名 def deco(*args, **kwargs): # 將所有引數原封不動的進行傳遞 print("在這個分割線之上寫函式執行前的操作") # -----------分割線----------- f = func(*args, **kwargs) # -----------分割線----------- print("在這個分割線之後,return之前,寫函式執行後的操作") return f # 如果 func 有返回值得話,需要在此return回去,否則,預設返回值為 None,一般預設都返回 return deco @func_name def test(parameter): # 8 print("test is running!") time.sleep(1) return "Returned value" # 該函式有返回值,所以需要在 裝飾器中的 deco 方法中 寫返回值 t = test('aa') print(t)
ok 裝飾器到此可以完事了,一般情況下都能滿足需求了,網上看那麼多原理,有點兒浪費時間,我偏向實操型,實在不喜歡囉嗦那麼多,就是幹。
當然在開發過程中, 我們可能會遇到一些特殊情況,比如引數問題
1、給裝飾器函式代引數(通用)
2、將執行函式的引數拆分計算等(比如:1000w的資料,拆分成100份執行等)(定製)
那就按順序來
1、寫一個代引數的裝飾器
def logging(level): def wrapper(func): def inner_wrapper(*args, **kwargs): print("[{level}]: enter function {func}()".format(level=level, func=func.__name__)) return func(*args, **kwargs) return inner_wrapper return wrapper @logging(level='INFO') def say(something): print("say {}!".format(something)) # 如果沒有使用@語法,等同於 # say = logging(level='INFO')(say) @logging(level='DEBUG') def do(something): print("do {}...".format(something)) if __name__ == '__main__': say('hello') do("my work")
發現:就是在上面的通用的模板上又套了一層!!!,然後拿到裡面的引數即可! so easy!!!
2、寫一個引數拆分的裝飾器,這個就稍微有點定製型了,不能像上面的一樣通用了,舉個 栗子:
def func_name(func): # 自定義裝飾器函式名 def deco(*args, **kwargs): # 將所有引數原封不動的進行傳遞 print(args[0]) f_list = [] for i in range(0,args[0],100000): print(i) f_list.append(func(i)) # f_list # 這兒應該按照既定規則,繼續對這個結果進行拼接,如果是寫檔案、入庫等操作,可以不用return return f_list # 這兒如果有返回值得話,應該是 return deco @func_name def test(parameter): # 8 print("test is running!") time.sleep(1) return "Returned value" # 該函式有返回值,所以需要在 裝飾器中的 deco 方法中 寫返回值 t = test(1000000) print(t)
可以看出來,這個的定製性稍微高點,不通用,但是我們實現了我們的需求,所以,我們最應該理解並學會的是怎麼用!!!
可以看出來,這個的定製性稍微高點,不通用,但是我們實現了我們的需求,所以,我們最應該理解並學會的是怎麼用!!!
下面在介紹一下基於類實現的裝飾器,那問題來了,我是實戰派,我並沒有用類裝飾器的需求,所以,當個大盜吧,以後用到了不至於瞎找了!!!
裝飾器函式其實是這樣一個介面約束,它必須接受一個callable物件作為引數,然後返回一個callable物件。在Python中一般callable物件都是函式,但也有例外。只要某個物件過載了__call__()方法,那麼這個物件就是callable的。
class Test(): def __call__(self): print 'call me!' t = Test() t() # call me
像__call__這樣前後都帶下劃線的方法在Python中被稱為內建方法,有時候也被稱為魔法方法。過載這些魔法方法一般會改變物件的內部行為。上面這個例子就讓一個類物件擁有了被呼叫的行為。
回到裝飾器上的概念上來,裝飾器要求接受一個callable物件,並返回一個callable物件(不太嚴謹,詳見後文)。
那麼用類來實現也是也可以的。我們可以讓類的建構函式__init__()接受一個函式,然後過載__call__()並返回一個函式,也可以達到裝飾器函式的效果。
class logging(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print "[DEBUG]: enter function {func}()".format( func=self.func.__name__) return self.func(*args, **kwargs) @logging def say(something): print "say {}!".format(something)
帶引數的類裝飾器
如果需要透過類形式實現帶引數的裝飾器,那麼會比前面的例子稍微複雜一點。那麼在建構函式里接受的就不是一個函式,而是傳入的引數。透過類把這些引數儲存起來。
然後在過載__call__方法是就需要接受一個函式並返回一個函式。
class logging(object): def __init__(self, level='INFO'): self.level = level def __call__(self, func): # 接受函式 def wrapper(*args, **kwargs): print "[{level}]: enter function {func}()".format( level=self.level, func=func.__name__) func(*args, **kwargs) return wrapper #返回函式 @logging(level='INFO') def say(something): print "say {}!".format(something)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4692/viewspace-2837147/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python中的裝飾器Python
- python中裝飾器的原理Python
- python類裝飾器的使用注意Python
- Python 工匠:使用裝飾器的技巧Python
- python使用裝飾器實現的事件中心(監聽器)Python事件
- python中的裝飾器介紹Python
- python的裝飾器Python
- 談一談Python中的裝飾器Python
- 深入理解Python中的裝飾器Python
- Python 中的閉包與裝飾器Python
- 裝飾器的使用
- Python的黑魔法@property裝飾器的使用技巧Python
- python的裝飾器@的用法Python
- python裝飾器的集中使用姿勢Python
- Javascript中裝飾器的實現原理JavaScript
- python裝飾器2:類裝飾器Python
- JavaScript裝飾器的使用JavaScript
- Python裝飾器的前世今生Python
- 使用 TypeScript 裝飾器裝飾你的程式碼TypeScript
- Python中裝飾器的基本概念和用法Python
- 介面測試使用Python裝飾器Python
- Python 裝飾器Python
- Python裝飾器Python
- python中contextmanager裝飾的方法PythonContext
- pytest fixtures裝飾器的使用
- python裝飾器decorator的應用Python
- python的裝飾器和閉包Python
- 瞭解python的裝飾器特性Python
- python幾種裝飾器的用法Python
- JavaScript中的裝飾器--DecoratorJavaScript
- Python 裝飾器原理Python
- Python裝飾器模式Python模式
- 1.5.3 Python裝飾器Python
- Python 裝飾器(一)Python
- Python中裝飾器語法詳解Python
- python裝飾器(披著羊皮的狼)Python
- python 實現類屬性的懶載入裝飾器Python
- web實戰:裝飾表格Web