python进阶:搞懂装饰器和切面编程
學習目標:
裝飾器、切面編程,實際使用體會。
紙上學來終覺淺
裝飾器和切面編程:
常見的函數,我們一般的返回值一個常見的數值或者列表,比如:
def mysum(a,b):return a + b result = mysum(1,2) print(result)mysum函數返回的是整數1+2的值,為3.
但是python神奇的地方就是,函數的返回值,可以是另一個函數。比如:
這樣,mysum_log的函數值是一個函數,賦給了變量mysum2,然后print直接用mysum2(1,2)就可以運行函數.此時的mysum2函數有點類似于mysum的功能,但是增加了print功能。
運行結果:
我們其實可以把變量mysum2直接改成mysum,改一下名字而已,結果就有點神奇了:
def mysum_log():print('input two number for sum ')def mysum(a,b):return a + breturn mysum mysum= mysum_log() print(mysum(1,2))這樣我們看起來像調用了mysum函數,但實際上我們還多了打印日志的print功能。業界成這個叫閉包–鬼知道為啥要叫這么個名字,還以為包pi有關。
這有什么用呢?單純看沒啥用,但是當這個mysum方式最初是別人寫的,而且別人不愿意改他的函數,可以通過這種方式豐富函數的功能。
舉個例子,隔壁老王寫了個函數:
laowangsum的功能是求平方和,但是沒有解釋,會讓人產生誤解,你叫老王修改函數,增加注釋,他懶不愿意動,怎么辦?
此時你想到能不能偷梁換柱,幫他增加點注釋,讓你的函數調用laowangsum會添加注釋log。于是:
你調用的laowangsum函數,實際上多運行了你的注釋,偷偷改了老王的函數的功能。這個是閉包的作用。
另一個需求:我們要求對每個函數都打印出日志信息,以便于錯誤時定位是哪個函數出了問題。或者進行函數大屏監控,怎么辦?
為每個函數都加入一個寫log的代碼?重復性太高,我們想辦法抽象起來,既然閉包可以改變函數功能,那用閉包就可以實現,但是現在的閉包需要寫明具體函數,不可能以后新增一個函數都去改一下閉包函數。此時就需要裝飾器,也叫切面編程。簡單來講,我把一個代表函數的變量傳進閉包函數,然后這個閉包函數就可以自適應傳進去的函數,自動調用它,不用每次新增函數都去修改閉包,只用調用一次閉包函數即可。
比如老王的函數定義時,加上一個@log_decorator,就可以自動幫他寫日志,他不用管日志這塊:
import functoolsdef log_decorator(function):@functools.wraps(function)def wrapper(*args,**kwargs):print('log begin')result = function(*args,**kwargs)print('log end')return resultreturn wrapper@log_decorator def laowangsum(a, b):return a ^ 2 + b ^ 2print(laowangsum(1, 2))運行結果:
log begin log end 7可以看到老王雖然自己只實現了加法邏輯,但是函數運行時,卻自動多了寫日志的功能,就像函數被砍了兩刀,自動加上了寫log的功能一樣。所以叫切面編程。
而且用print(laowangsum.name)打印出來,laowangsum確實就是老王自己定義的函數,名字沒有變化,沒有被偷梁換柱,因為是@functools.wraps(function)的原因。
裝飾類:
除了函數,還可以用裝飾類,大同小異。把函數替換成類
class log:def __init__(self,func):self.func = funcself.num_calls = 0 #函數調用次數def __call__(self, *args, **kwargs):self.num_calls += 1print('number of calls is :{}'.format(self.num_calls))return self.func(*args, **kwargs)@log def example():print('I am being called')example() example() example()結果:
number of calls is :1 I am being called number of calls is :2 I am being called number of calls is :3 I am being calledlog類自動幫助統計了函數被調用次數。
結論:
裝飾器經常用在:
1、 寫日志
2、統計運行時間
3、 校驗輸入數據的有效性和用戶認證等
總結
以上是生活随笔為你收集整理的python进阶:搞懂装饰器和切面编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python字典排序及字典集合去重高阶教
- 下一篇: SparkException: Pyth