1. 程式人生 > >python中的遞迴函式

python中的遞迴函式

  在一個函式內部,可以呼叫其他函式,假如一個函式在其內部可以呼叫自己,那麼這個函式就是遞迴函式。
  在計算數學中的階乘時,我們常用for迴圈或者遞迴函式來實現,例如:
計算9的階乘:
sum = 0
for i in range(1,10):
    sum *= i
print(sum)

使用遞迴函式實現:
def me(x):
    if x == 1:
        return x
    return x* me(x-1)
計算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)這種資料結構實現的,每當進入一個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位。比如你輸入個1000,他就會提示錯誤:RuntimeError: maximum recursion depth exceeded in comparison。
而為了防止棧 的溢位;我們可以使用尾遞迴優化,尾遞迴是指,在函式返回的時候,呼叫自身本身,並且,return語句不能包含表示式。這樣,編譯器或者直譯器就可以把尾遞迴做優化,使遞迴本身無論呼叫多少次,都只佔用一個棧幀,不會出現棧溢位的情況,尾遞迴的實現方式是 :使函式本身返回的是函式本身。
使用遞迴函式的優點是邏輯簡單清晰,缺點是過深的呼叫會導致棧溢位。遺憾的是,大多數程式語言沒有針對尾遞迴做優化,Python直譯器也沒有做優化,任何遞迴函式都存在棧溢位的問題。遞迴函式的使用之處有 斐波那契額數列,漢諾塔的移動。