1. 程式人生 > 其它 >Python之遞迴函式

Python之遞迴函式

Python之遞迴函式 好久沒有更新內容了,也好久沒有給大家打個招呼了,小白想死你們了。今天跟大家說說Python中的遞迴函式。

Python是支援遞迴函式的。簡單地說,一個遞迴函式就是直接或間接地呼叫自身的函式,並且要有退出條件。枯燥的概念令人生厭,我們直接來個例子看看遞迴函式是如何工作的。

例如我們對一個數字列表進行求和計算,我們可以使用內建的sum函式或者自己寫一個函式來完成計算工作,接下來我們看看如何使用遞迴來完成求和運算:

In[1]: def mysum(L):
  ...:    if not L:
  ...:        return 0
  ...:    else:
  ...:        return L[0] + mysum(L[1:])
  ...:    

In[2]: mysum([1, 2, 3, 4, 5])
Out[2]: 15

如果對上面的函式較為困惑,可以使用print函式來列印每次遞迴時列表L的值:

In[3]: def mysum(L):
  ...:    print(L)
  ...:    if not L:
  ...:        return 0
  ...:    else:
  ...:        return L[0] + mysum(L[1:])
  ...:    

In[4]: mysum([1, 2, 3, 4, 5])
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]
Out[4]: 15

通過上述的輸出可以發現:每次遞迴時,列表的長度都變短了,直到列表變為空時,遞迴終止。

對於上面的程式碼,我們可以使用另外一種程式碼形式來實現,也就是使用三目運算子,然而在Python中是沒有三目運算子的,不過可以使用if/else來實現,程式碼如下:

In[1]: def mysum(L):
  ...:    return 0 if not L else L[0] + mysum(L[1:])
  ...: 

In[2]: mysum([1, 2, 3, 4, 5])
Out[2]: 15

說到遞迴還有一個階乘的例子要個大家說說:

In[5]: def factorial(number):
  ...:    if number <=1:
  ...:        return 1
  ...:    else:
  ...:        return number * factorial(number-1)
  ...:    

In[6]: for i in range(11):
  ...:    print("{0:2}! = {1}".format(i, factorial(i)))
  ...:    
 0! = 1
 1! = 1
 2! = 2
 3! = 6
 4! = 24
 5! = 120
 6! = 720
 7! = 5040
 8! = 40320
 9! = 362880
10! = 3628800

如果計算factorial(5),可以根據函式定義看到其計算過程:

===> factorial(5)
===> 5 * factorial(4)
===> 5 * (4 * factorial(3))
===> 5 * (4 * (3 * factorial(2)))
===> 5 * (4 * (3 * (2 * factorial(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

使用遞迴函式需要注意防止棧溢位。在計算機中,函式呼叫是通過棧(stack) 這種資料結構實現的,每當進入一個函式呼叫,棧就會加一層棧幀,每當函 數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的 次數過多,會導致棧溢位。可以試試factorial(1000):

>>> factorial(1000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in factorial
  ...
  File "<stdin>", line 4, in factorial
RuntimeError: maximum recursion depth exceeded

使用遞迴函式的優點是邏輯簡單清晰,缺點是過深的呼叫會導致棧溢位。

今天的內容就到這裡,明天繼續。