引言: 這部分關于裝飾器的內容需要前面閉包的知識作為基礎。裝飾器有點類似于我們java web里面經常講到的面向切面編程(AOP),一切原理都是相通的。 一.什么是AOP 簡單點來說,其實是為了更好的對程序進行控制,提高代碼的可重用性。 在某段程序執行前面加上我們的控制代碼。其實就是對原有函數進行了一層包裝。(裝飾器通俗點來說,就是對函數的二次封裝)
下面我將通過一個案例來說明。 在我們開發java web網站時,我們需要對用戶訪問的網頁進行驗證工作,并記錄下用戶的網頁瀏覽軌跡。我們的邏輯代碼通常是:
1)驗證用戶是否登陸,并且是否有該權限2)返回用戶相應需要的網頁資源3)對用戶進行記錄此時我們知道只有(2)才是我們的核心業務,(1),(3)是用于控制權限,分析等用途。如果我們需要對所有的網頁都進行如上的操作,是否我們(1),(3)這部分公共的控制代碼都需要放入所有的程序中。這樣一來產生了很多垃圾代碼,不利于程序的可重用性。二來,不利于以后的維護,如果(1),(3)中代碼需要修改,那我們需要修改所有涉及到(1),(3)的代碼。面向切面編程就是把公用的代碼段抽取出來,在每個需要執行的程序中自動執行這段代碼即可。不需要修改原有的程序。
#程序1:validate() #validate the authorityPRocess1() #process the user1 needlog() #log the user recorder#程序2:validate() #validate the authorityprocess1() #process the user1 needlog() #log the user recorder#修改后程序:def Operate(process): validate() process() log()#如我們需要執行process1,()則我們執行operate(process1)即可。同理process2,這時我們操作的是一個經過包裝的process函數。二.閉包編程實現
def wrap(some_func): def inner(): print("用戶驗證...") some_func() print("記錄用戶信息") return innerdef process1(): print("process1")def process2(): print("process2")#對process1進行包裝process1=wrap(process1)process1()#對process2進行包裝process1=wrap(process2)process2()三.裝飾器 裝飾器其實就是提供閉包實現的語法糖@,裝飾器就是對函數的二次封裝。只要在需要包裝的函數上面放入@wrapper即可。
def wrap(some_func): def inner(): print("用戶驗證...") some_func() print("記錄用戶信息") return inner@wrapdef process1(): print("process1")@wrapdef process2(): print("process2")#對process1進行包裝process1()#對process2進行包裝process2()那么如何實現更通用的裝飾器呢,真是場景中,我們需要通過參數傳遞來進行程序間的通信。python中提供了*args,**kwags這個不確定的參數形式,*args是不定長參數,**kwags是以字典形式存在的不定長參數。 我們通過實例來熟悉相關用戶。
def wrap(some_func): def inner(*args,**kwags): print("before") ret=some_func(*args,**kwags) print("after") return ret return inner@wrap #對加法進行包裝def add(a,b): return a+b@wrap #對減法進行包裝def sub(a,b,c): return a-b-c#對process1進行包裝result=process1(1,2)print(result) #執行結果為3#對process2進行包裝t=process2(5,2,1)print(t) #執行結果為2新聞熱點
疑難解答