標籤:python 裝飾器 遞迴
今天又花了多半天來學習裝X利器---裝飾器,
來詳細的講講裝飾器的用法
還是要說一下,學裝飾器之前要先搞清楚什麼是函數。裝飾器就是對函數進行一個封裝,打個比喻來說就是:
假設有一個箱子A,在箱子A的外面又套了一個大箱子,外面的大箱子還起名叫A,以後在找裡面的小箱子A的時候,就先去找外面的大箱子A,開啟外面的大箱子A之後 在開啟內部的小箱子A,這個就是裝飾器。
裝飾器也是一個函數,至少兩層
def outter(func): #定義函數 outter,參數為一個函數的函數名,這裡為func, def inner(): #定義函數inner print "before" tmp = func() #執行函數func(), 這裡的func為outter的參數 print "after" return tmp return inner # 返回函數名inner@outter # 給下面的函數加裝飾器,這裡是一個文法糖def foo(): # 定義函數foo print "foo"foo() #指定函數foo(),這裡的 foo() 函數為經過裝飾器裝飾的函數
輸出:
before
foo
after
2. 執行上面代碼的時候,被裝飾的函數foo()的函數名foo作為參數,即outter(foo); outter函數的傳回值,重新賦值給被裝飾的函數的函數名
3.裝飾器可以裝飾有N(N>=0)個參數的函數,對於有不同個數參數的函數來說,裝飾器使用動態參數來處理傳參的問題,我們修改上面的例子,修改後就解決了傳參的問題:
4. 函數的傳回值,如果函數有傳回值,我們就要考慮函數的傳回值如何傳遞迴來,直接將函數的返回結果return就可以了:
def outter(func): def inner(*args,**kwargs): #設定參數 print "before" tmp = func(*args,**kwargs) #設定參數,這裡的參數和inner的參數一樣 print "after" return tmp # 變數tmp的值為func(*args,**kwargs)的執行結果,返回裝飾後函數的傳回值 return inner@outterdef foo(arg,*args): print arg,"---",argsfoo(1,2,3,4)
5.多裝飾器
一個函數可以被多個函數同時裝飾,函數被多個裝飾器裝飾的時候,效果類似於俄羅斯套娃。
def w1(fun): def inner(): print "w1,before" fun() print "w1,after" return innerdef w2(fun): def inner(): print "w2,before" fun() print "w2,after" return inner@w2@w1def foo(): print "foo"foo()
執行結果
w2,beforew1,beforefoow1,afterw2,after
6. 帶參數的裝飾器(至少三層)
就是給函數加裝飾器的時候,裝飾器還帶有參數,代碼如下:
def Filter(before_func,after_func): pass@Filter(Before, After)def Index(request,kargs): pass
現在上完整代碼,然後解釋:
def Before(request,kargs): #1 載入Before函數到記憶體 #14 執行函數 Before print ‘before‘ #15 執行print語句 def After(request,kargs): #2 載入After到記憶體 #21 執行After函數 print ‘after‘ #22 執行print語句 def Filter(before_func,after_func): #3 載入函數Filter到記憶體 #5 執行裝飾器Filter def outer(main_func): #6 載入函數outer到記憶體 #8 執行函數outer def wrapper(request,kargs): #9 載入函數wrapper #12 執行函數wrapper before_result = before_func(request,kargs) #13 給before_result賦值 if(before_result != None): # 16 執行if語句,這裡判斷為假 return before_result main_result = main_func(request,kargs) #17 給變數main_result賦值 if(main_result != None): #19 執行if語句,這裡判斷為假 return main_result after_result = after_func(request,kargs) #20 給after_result賦值 if(after_result != None): #23 執行if語句, 這裡判斷為假 return after_result return wrapper #10 返回函數outer的傳回值,warapper return outer #7 返回Filter函數的傳回值,即函數名outer @Filter(Before, After) #4 發現裝飾器Filter, #17 執行Filter(Before, After) def Index(request,kargs): print ‘index‘ #18 執行print語句 Index("quest0","kwargs0") #11 執行函數 Index
###############################################################
遞迴
遞迴演算法是一種 直接或間接的調用自身的一種演算法。
打個比喻來說就向下面這樣
從前有座山,山上有座廟,廟裡有個老和尚,老和尚對小和尚說:從前有座山,山上有座廟,廟裡有個老和尚,老和尚對小和尚說:從前有座山,山上有座廟,廟裡有個老和尚,老和尚對小和尚說。。。。。。。。
遞迴演算法可以有效解決一大類問題,比如經典的 漢諾塔(又稱河內塔)問題,
遞迴演算法的特點是
1. 在函數或者過程裡調用自身
2. 必須有一個明確的條件,可以讓遞迴結束
3. 演算法簡潔,但是效率低
4. 容易造成棧溢出(因為在執行過程中,每一層的返回點、局部變數等都要開闢棧來儲存)
以實現斐波那契數列為例:
def fib(a1,a2): # print a1,a2, a3=a1+a2 if a3>100: #這裡加入了結束條件,如果沒有這個條件,會形成死迴圈 return a3 # print a3, return fib(a2,a3) # fib(a2,a3)print fib(0,1)
遞迴是可以和while互相轉換的。
上面的代碼用while迴圈來實現的的代碼是:
a1,a2 = 0,1
while a1<200:
print a1
a2=a1+a2
a1=a2-a1
http://timesnotes.blog.51cto.com/1079212/1716574
http://www.timesnotes.com/?p=114
本文出自 “Will的筆記” 部落格,請務必保留此出處http://timesnotes.blog.51cto.com/1079212/1716574
python學習筆記-Day05-第一部分(再談裝飾器)(遞迴)