Python——遞迴函式
阿新 • • 發佈:2019-02-14
一. 遞迴函式
遞迴函式就是函式在內部呼叫自身。
必須有一個明確的遞迴結束條件,稱為遞迴出口。
注意: 切勿忘記遞迴出口,避免函式無限呼叫。
函式呼叫自身的實現:
其實函式每次被呼叫時都會建立一個新名稱空間,也就是當函式呼叫“自身”時,實際上執行的是兩個不同的函式(也可以說一個函式具有兩個不同的名稱空間)。
【例】定義階乘函式
遞迴實現:
>>> def fact(n): ... if n == 1: ... return 1 ... else: ... return n * fact( n-1 ) ... >>> >>> fact(1) 1 >>> fact(2) 2 >>> fact(4) 24 >>> fact(5) 120
fact(5) 計算過程:
factorial(5) # 第 1 次呼叫使用 5 5 * factorial(4) # 第 2 次呼叫使用 4 5 * (4 * factorial(3)) # 第 3 次呼叫使用 3 5 * (4 * (3 * factorial(2))) # 第 4 次呼叫使用 2 5 * (4 * (3 * (2 * factorial(1)))) # 第 5 次呼叫使用 1 5 * (4 * (3 * (2 * 1))) # 從第 5 次呼叫返回 5 * (4 * (3 * 2)) # 從第 4 次呼叫返回 5 * (4 * 6) # 從第 3次呼叫返回 5 * 24 # 從第 2 次呼叫返回 120 # 從第 1 次呼叫返回
迭代實現:
>>> def fact(n):
... result = 1
... for i in range(2,n+1):
... result *= i
... return result
...
>>>
>>> fact(1)
1
>>> fact(2)
2
>>> fact(5)
120
遞迴的優缺點:
優點:
- 遞迴使程式碼看起來更加整潔、優雅
- 可以用遞迴將複雜任務分解成更簡單的子問題
- 使用遞迴比使用一些巢狀迭代更容易
缺點:
- 遞迴的邏輯很難除錯、跟進
- 遞迴呼叫的代價高昂(效率低),因為佔用了大量的記憶體和時間。
二. 尾遞迴
使用遞迴函式需要注意防止棧溢位。在計算機中函式呼叫是通過棧這種資料結構實現的。每當進入一個函式呼叫,棧就會加一層棧幀;每當函式返回就會減一層棧幀。由於棧的大小不是無限的,因此遞迴呼叫次數過多會導致棧溢位。
解決遞迴呼叫棧溢位的方法是通過尾遞迴優化。
尾遞迴是指函式返回時呼叫函式本身,並且 return 語句不能包含表示式。這樣,編譯器和直譯器就可以對尾遞迴進行優化。使遞迴本身無論呼叫多少次都只佔用一個棧幀,從而避免棧溢位的情況。
>>> def fact(n):
... return fact_iter(n,1)
...
>>>
>>> def fact_iter(num , result):
... if num == 1:
... return result
... return fact_iter(num-1 , num * result)
...
>>>
>>>
>>> fact(1)
1
>>> fact(2)
2
>>> fact(5)
120