在函式內部,可以呼叫其他函式。如果乙個函式在內部呼叫自身本身,這個函式就是遞迴函式。
舉個例子,我們來計算階乘n! = 1 x 2 x 3 x ... x n
,用函式fact(n)
表示,可以看出:
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
所以,fact(n)
可以表示為n x fact(n-1)
,只有n=1時需要特殊處理。
於是,fact(n)
用遞迴的方式寫出來就是:
deffact(n):
if n==1:
return 1
return n * fact(n - 1)
如果我們計算fact(5)
,可以根據函式定義看到計算過程如下:
===> fact(5)===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
遞迴函式的優點是定義簡單,邏輯清晰。理論上,所有的遞迴函式都可以寫成迴圈的方式,但迴圈的邏輯不如遞迴清晰。
使用遞迴函式需要注意防止棧溢位。在計算機中,函式呼叫是通過棧(stack)這種資料結構實現的,每當進入乙個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位。可以試試fact(1000)
:
>>> fact(1000)traceback (most recent call last):
file
"", line 1, in
file
"", line 4, in
fact
...file
"", line 4, in
fact
runtimeerror: maximum recursion depth exceeded
in comparison
解決遞迴呼叫棧溢位的方法是通過尾遞迴優化,事實上尾遞迴和迴圈的效果是一樣的,所以,把迴圈看成是一種特殊的尾遞迴函式也是可以的。
尾遞迴是指,在函式返回的時候,呼叫自身本身,並且,return語句不能包含表示式。這樣,編譯器或者直譯器就可以把尾遞迴做優化,使遞迴本身無論呼叫多少次,都只占用乙個棧幀,不會出現棧溢位的情況。
上面的fact(n)
函式由於return n * fact(n - 1)
引入了乘法表示式,所以就不是尾遞迴了。要改成尾遞迴方式,需要多一點**,主要是要把每一步的乘積傳入到遞迴函式中:
deffact(n):
return fact_iter(n, 1)
deffact_iter(num, product):
if num == 1:
return
product
return fact_iter(num - 1, num * product)
-----------------自己練習**----------------------
in [3]: def rfn(x,total=1):...:
if x == 1:
...:
return
total
...:
return rfn(x-1,x*total)
...:
in [4]: rfn(3)
out[4]: 6
-----------------自己練習**----------------------
可以看到,return fact_iter(num - 1, num * product)
僅返回遞迴函式本身,num - 1
和num * product
在函式呼叫前就會被計算,不影響函式呼叫。
fact(5)
對應的fact_iter(5, 1)
的呼叫如下:
===> fact_iter(5, 1)===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
尾遞迴呼叫時,如果做了優化,棧不會增長,因此,無論多少次呼叫也不會導致棧溢位。
遺憾的是,大多數程式語言沒有針對尾遞迴做優化,python直譯器也沒有做優化,所以,即使把上面的fact(n)
函式改成尾遞迴方式,也會導致棧溢位。
python遞迴函式例項 python遞迴函式
python遞迴函式 什麼是遞迴?遞迴,就是在函式執行中自己呼叫自己 示例 def recursion n 定義遞迴函式 print n 列印n recursion n 1 在函式的執行種呼叫遞迴 recursion 1 呼叫函式 這個函式在不斷的自己呼叫自己,每次呼叫n 1,看下執行結果 998t...
python靜態遞迴函式 python遞迴函式
一 遞迴的定義 1.什麼是遞迴 在乙個函式裡在呼叫這個函式本身 2.最大遞迴層數做了乙個限制 997,但是也可以自己限制 1 deffoo 2 print n 3 n 1 4 foo n 5 foo 1 驗證997 3.最大層數限制是python預設的,可以做修改,但是不建議你修改。因為如果用997...
python靜態遞迴函式 python 遞迴函式
前言 本篇關於遞迴基本借鑑下面部落格講解加入自己理解。1.遞迴函式定義 如果乙個函式在函式內部呼叫自己,那這個函式就是遞迴函式。如 defsum arg,stop print arg if arg arg arg sum arg,stop sum 1,20 2.遞迴的特性 1 必須有乙個明確的結束條...