今晚看了函數的遞歸,在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
聯想到之前用循環寫的關於求一百以內的數的和,目前看來基本上有三種寫法:
1. for 循環
sum = 0
for i in range(1,101):
sum = sum +i
print sum
2 while 循環:
sum =0
i =1
while i <101:
sum = sum +i
i = i +1
print sum
3. 遞歸函數:
def fact(n):
return fact_iter(0,1,n)
def fact_iter(product, count, max):
if count >max:
return product
return fact_iter(product+count, count+1, max)
print fact(100)
對應的求100以內的數的乘法,寫法如下:
for循環
sum = 1
for i in range(1,101):
sum = sum *i
print sum
2.while循環
sum =1
i =1
while i <101:
sum = sum *i
i = i +1
print sum
3. 遞歸函數:
def fact(n):
return fact_iter(1,1,n)
def fact_iter(product, count, max):
if count >max:
return product
return fact_iter(product*count, count+1, max)
print fact(100)
使用遞歸函數需要注意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。
解決遞歸調用棧溢出的方法是通過尾遞歸優化,事實上尾遞歸和循環的效果是一樣的,所以,把循環看成是一種特殊的尾遞歸函數也是可以的。
尾遞歸是指,在函數返回的時候,調用自身本身,並且,return語句不能包含表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優化,使遞歸本身無論調用多少次,都只佔用一個棧幀,不會出現棧溢出的情況。
使用遞歸函數的優點是邏輯簡單清晰,缺點是過深的調用會導致棧溢出。
針對尾遞歸優化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實上和循環是等價的,沒有循環語句的編程語言只能通過尾遞歸實現循環。