1. 程式人生 > >【Rollo的Python之路】高階函數,遞歸函數 學習筆記

【Rollo的Python之路】高階函數,遞歸函數 學習筆記

使用遞歸 包含 n) ron 結束 學習筆記 標準 python style

高階函數:

變量可以指向函數,函數可以做為了參數被另一個函數調用,這種帶函數為參數的函數就是高階函數。

1.0 函數本身也可以賦值給變量,即:變量可以指向函數。

2.0 函數名也可以做為變量,給其他給函數做參數,同時調用函數名。

def num(n):
    return n*n
print(num(4))


def fuc(x,y,num):
    return num(x) + num(y)

print(fuc(1,2,num))


#執行結果:

16
5

遞歸函數:

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數

必須條件:

1.0 調用本身函數。

2.0 必要一有一個結束條件

3.0 相鄰兩次重復之間有緊密的聯系,前一次要為後一次做準備(通常前一次的輸出就作為後一次的輸入)。

4.0 遞歸效率不高,遞歸層次過多會導致棧溢出。一般不使用

5.0 能用遞歸的,都用能for循環解決

def recursive_function(x):
    if x==1:
        return 1
    return  x*recursive_function(x-1)

print(recursive_function(5))

#執行結果:

120

其運行過程:

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

遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。

使用遞歸函數需要註意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。

解決遞歸調用棧溢出的方法是通過尾遞歸優化,事實上尾遞歸和循環的效果是一樣的,所以,把循環看成是一種特殊的尾遞歸函數也是可以的。

尾遞歸是指,在函數返回的時候,調用自身本身,並且,return語句不能包含表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優化,使遞歸本身無論調用多少次,都只占用一個棧幀,不會出現棧溢出的情況。

小結

使用遞歸函數的優點是邏輯簡單清晰,缺點是過深的調用會導致棧溢出。

針對尾遞歸優化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實上和循環是等價的,沒有循環語句的編程語言只能通過尾遞歸實現循環。

Python標準的解釋器沒有針對尾遞歸做優化,任何遞歸函數都存在棧溢出的問題。

【Rollo的Python之路】高階函數,遞歸函數 學習筆記