【Rollo的Python之路】高階函數,遞歸函數 學習筆記
高階函數:
變量可以指向函數,函數可以做為了參數被另一個函數調用,這種帶函數為參數的函數就是高階函數。
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之路】高階函數,遞歸函數 學習筆記