Python3之從遞迴到閉包再到裝飾器
遞迴
遞迴指的是函式直接或間接的呼叫自身。
有一則故事:
從前有座山,山裡有座廟,廟裡有個老和尚,老和尚在給小和尚講故事,故事的內容是:從前有座山,山裡有座廟。。。。
可能圖片更直觀,相信都見過類似的圖片吧
說明:
- 遞迴一定要控制遞迴的次數,當符合某一條件時要終止遞迴呼叫
- 幾乎所有的遞迴都能用while迴圈來代替
遞迴的優缺點:
優點:可以把問題簡單化,讓思路更加清晰,程式碼更簡潔
缺點:遞迴因系統環境影響大,當遞迴深度太大時,可能會得到不可預知的結果
遞迴呼叫分為兩個階段:
遞推階段:從原問題出發,按遞迴公式遞推,從未知到已知,最終達到遞迴終止條件
迴歸條件:按遞迴終止條件求出結果,逆向逐步帶入遞迴公式,迴歸到原問題求解
先舉個遞迴的栗子吧,我就喜歡舉例子,文字描述總不如栗子更容易理解,也正好了解一下在什麼請況下使用遞迴比較好吧
如老和尚講故事:
def f():
print('從前有座山,山裡有座廟,廟裡有個老和尚講故事,講的是:')
f()
f()
結果呢:
這個就是沒有加限制此數,最後崩潰掉了
再如,用遞迴求階乘:
def myfac(n):
if n == 1: # 限制條件,當為 1 時終止遞迴
return 1
return n * myfac(n - 1)
print(myfac(5)) # 5 的階乘 120
遞推過程:
5! = 5 * 4!
5! = 5 * 4 * 3!
5! = 5 * 4 * 3 * 2!
5! = 5 * 4 * 3 * 2 * 1!
5! = 5 * 4 * 3 * 2 * 1
迴歸過程:
5! = 5 * 4 * 3 * 2
5! = 5 * 4 * 6
5! = 5 * 24
5! = 120
配個圖:
閉包
什麼是閉包:
如果一個內嵌函式訪問了外部巢狀函式的變數,則這個內嵌函式就是閉包
閉包必須滿足三個條件:
- 必須是一個內嵌函式
- 內嵌函式必須引用外部函式的變數
- 外部函式返回值必須是內嵌函式
舉個栗子:
分析以上程式碼:
pow2接收的返回值是什麼? —–> fn , 沒錯,就是fn,因為maker_power內部的 fn 是一個函式,但此時沒被呼叫,所以return 的 fn 就是一個函式名。強調:此函式雖然沒被呼叫,但是 y 是不會被釋放的。
此時的pow2實際上就是 fn 了
pow2(5) 在這時其實就是呼叫fn 函式了,並把 5 傳進去,即x = 5,上邊說的 有 y 還沒有被釋放,返回x 的 y 次方,即返回5^2=25
注意:fn 是函式名 fn()才是呼叫 fn 函式(即,函式名加括號才是呼叫)
再來個溫習一下:
裝飾器
裝飾器是一個函式,傳入的是一個函式,返回的也是一個函式
例如:
def 裝飾器函式名(引數):
語句塊
return 函式物件
@裝飾器函式名
def 函式名(形參列表):
語句塊
裝飾器的原理:
被裝飾函式的變數(函式名)繫結裝飾器函式呼叫後返回的函式
舉幾個例子:
def mydeco(fn):
def fx():
print('fx正在被呼叫')
return fx
def myfun():
print('myfun正在被呼叫')
myfun = mydeco(myfun)
myfun() # 結果:fx正在被呼叫 為什麼不是myfun正在被呼叫?
先理解這個例子,
mydeco(myfun) 這句是呼叫mydeco函式,引數是一個函式myfun,即fn = myfun,返回fx,即接收的myfun=fx,
myfun()就是呼叫fx(),執行print(‘fx正在被呼叫’)這句話,所以列印的不是myfun正在被呼叫,跟他根本沒有關係。
另一個寫法:
def mydeco(fn):
def fx():
print('fx正在被呼叫')
return fx
@mydeco
def myfun():
print('myfun正在被呼叫')
# myfun = mydeco(myfun)
myfun()
再深入一層講解裝飾器:
先看程式碼:
def mydeco(fn):
def fx():
print('這是被裝飾之前')
fn() # 呼叫被裝飾函式
print('這是被裝飾之後')
return fx
@mydeco
def myfun():
print('myfun正在被呼叫')
myfun()
myfun() 再次講解這句話,加深理解上邊的栗子
myfun實際可以寫成兩句話:
myfun = mydeco(myfun)
myfun()
初步可認為是呼叫myfun函式,但是myfun有裝飾器,所以myfun會當做一個引數傳入裝飾器函式裡,即fn = myfun,呼叫mydeco函式,先執行print(‘這是被裝飾之前’)這就話,然後執行fn()函式,即呼叫myfun()函式,執行print(‘myfun正在被呼叫’)這句話,fn()函式執行完畢,繼續執行裝飾器函式,執行print(‘這是被裝飾之後’)這句話,
所以最後列印結果是:
這是被裝飾之前
myfun正在被呼叫
這是被裝飾之後
裝飾器應用:
def privieged_check(fn):
def fx(name, x):
print('正在進行驗證...')
if True:
fn(name, x)
else:
print('許可權驗證失敗')
return fx
def message_send(fn):
def fy(name, money):
fn(name, money)
print('正在傳送短息給', name)
return fy
@message_send
@privieged_check
def savemoney(name, x):
print(name, '存錢', x, '元')
savemoney('小張', 200)
注意:如果被裝飾的函式有多個裝飾器,優先執行最近的
執行結果:
正在進行驗證...
小張 存錢 200 元
正在傳送短息給 小張
執行過程:
其實自己繞繞也就繞出來了!
願意和大家一起交流,huamuxiong_2018@163.com
本節圖有網上百度的,有助於理解,如果有侵權,還請告知,我會刪除,謝謝
相關文章
- Python:從閉包到裝飾器Python
- 裝飾器&遞迴遞迴
- 迭代器,閉包,遞迴遞迴
- 閉包與裝飾器
- Python進階之閉包和裝飾器Python
- 【python】閉包與裝飾器Python
- Python閉包與裝飾器Python
- 裝飾器中閉包之加認證功能
- 從【預編譯】到【宣告提升】到【作用域鏈】再到【閉包】編譯
- python高階-閉包-裝飾器Python
- python的裝飾器和閉包Python
- python_August(閉包、裝飾器)Python
- Python_閉包和裝飾器Python
- Python高階 -- 11 閉包、裝飾器Python
- 閉包函式,裝飾器詳解函式
- Python 中的閉包與裝飾器Python
- Python提高:關於閉包和裝飾器Python
- 函式物件、裝飾器、閉包函式函式物件
- 13. 閉包函式與裝飾器函式
- Python3 裝飾器解析Python
- Python 簡明教程 --- 22,Python 閉包與裝飾器Python
- wrap裝飾器包
- python3 裝飾器全解Python
- Python學習之路26-函式裝飾器和閉包Python函式
- 深入理解閉包,裝飾器,深拷貝淺拷貝
- JS函式表示式——函式遞迴、閉包JS函式遞迴
- Python3之遞迴函式簡單示例Python遞迴函式
- 小甲魚python學習總結之函式——lambda fillter() map() 閉包 遞迴Python函式遞迴
- python 之裝飾器(decorator)Python
- 【React深入】從Mixin到HOC再到HookReactHook
- Python深入分享之裝飾器Python
- Python 語法之裝飾器Python
- Python之函式裝飾器Python函式
- 用閉包替換遞迴實現斐波拉契數列遞迴
- 《流暢的Python》 讀書筆記 第7章_函式裝飾器和閉包Python筆記函式
- python裝飾器2:類裝飾器Python
- 利用閉包傳遞引數
- 設計模式之-裝飾器模式設計模式