實際開發過程當中可能要對某些方法或者流程做出改進,添加監控,添加日志記錄等
所以我們要去改動已有的代碼,自己的或者別人的,但改動后測試不周會引發不可控的異常,aop 模式解決了這類問題
引發重復代碼大量積累,裝飾器解決了些類問題
1:基礎篇
import functools #采用functools.wraps的目的是為了使裝飾器返回的類型始終是func的類型,否則將返回嵌套高階函數的中的類型,例如返回的是wraper #采用參數*args ,**kw是解決函數多參數的問題 def log(func): @functools.wraps(func) def wrapper(*args, **kw): print 'call %s():' % func.__name__ return func(*args, **kw) return wrapper #修飾器參數的情況 def logger(pram): def log(func): @functools.wraps(func) def wrapper(*args, **kw): print 'call %s(): and parsms is %s' %(func.__name__,pram); return func(*args, **kw); return wrapper; return log; @log def showMesage(name,age): print("my name is {0} and my age is {1}".format(name,age)); @logger("hello") def getMessage(name,age): print("my name is {0} and my age is {1}".format(name,age)); #添加多個修飾器來拓展所需的功能 @log @logger("hello15466") def recieveMessage(name,age): print("my name is {0} and my age is {1}".format(name,age)); if __name__=='__main__': showMesage("ddd",21); getMessage("aaa",43); recieveMessage("ccc",34);
2:通過一個實用性的示例來繼續描述下裝飾器的使用場景,這次我將裝飾器提取到類中,需要調用的地方通過類的引用來調取
下面這個示例演示的是一個監控程序運行時間的,如下:
一: 建立一個監控類[monitor.py]:
import functools; import time; class monitor: @staticmethod def startmonitor(): return time.clock(); @staticmethod def endmonitor(): return time.clock(); def listener(listen): def log(func): @functools.wraps(func) def wrapper(*args, **kw): startime=listen.startmonitor(); f=func(*args, **kw); endtime=listen.endmonitor(); print("total time is {0}".format(startime-endtime)); return f; return wrapper; return log;
二:在需要使用的地方來調用監控
from monitor import *; @listener(monitor) def getinfo(): print("hello ,welcome!"); if __name__=="__main__": getinfo();