Python棧溢出【新手必學】

python3.5.4python


遞歸函數最噁心的時候莫非棧溢出(Stack overflow)。
PS:另外不少人在學習Python的過程當中,每每由於沒有好的教程或者沒人指導從而致使本身容易放棄,爲此我建了個Python交流.裙 :一久武其而而流一思(數字的諧音)轉換下能夠找到了,裏面有最新Python教程項目可拿,不懂的問題多跟裏面的人交流,都會解決哦!編程

如何解決?網絡

人爲設置遞歸深度
使用python寫的遞歸程序若是遞歸太深, 那麼極有可能由於超過系統默認的遞歸深度限制而出現錯誤。通常默認遞歸長度在1000左右。
RuntimeError: maximum recursion depth exceeded in comparison編程語言

顯然此時咱們能夠人爲修改函數

import sys
sys.setrecursionlimit(1000000) #括號中的值爲遞歸深度
尾遞歸優化
注:這只是一種思惟的科普
解決遞歸調用棧溢出的另外一種方法是經過尾遞歸優化,事實上尾遞歸和循環的效果是同樣的,因此,把循環當作是一種特殊的尾遞歸函數也是能夠的。學習

尾遞歸是指,在函數返回的時候,調用自身自己,而且,return語句不能包含表達式。這樣,編譯器或者解釋器就能夠把尾遞歸作優化,使遞歸自己不管調用多少次,都只佔用一個棧幀,不會出現棧溢出的狀況。優化

上面的fact(n)函數因爲return n * fact(n - 1)引入了乘法表達式,因此就不是尾遞歸了。要改爲尾遞歸方式,須要多一點代碼,主要是要把每一步的乘積傳入到遞歸函數中:blog

def fact(n):
return fact_iter(n, 1)教程

def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
能夠看到,return fact_iter(num - 1, num * product) 僅返回遞歸函數自己,num - 1和num * product在函數調用前就會被計算,不影響函數調用。遞歸

fact(5)對應的fact_iter(5, 1)的調用以下:

===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
尾遞歸調用時,若是作了優化,棧不會增加,所以,不管多少次調用也不會致使棧溢出。

遺憾的是,大多數編程語言沒有針對尾遞歸作優化,Python解釋器也沒有作優化,因此,即便把上面的fact(n)函數改爲尾遞歸方式,也會致使棧溢出。

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

小結方法一:人爲修改默認遞歸長度 方法二:人爲修改python解釋器,將其優化,會十分有趣———PS:另外不少人在學習Python的過程當中,每每由於沒有好的教程或者沒人指導從而致使本身容易放棄,爲此我建了個Python交流.裙 :一久武其而而流一思(數字的諧音)轉換下能夠找到了,裏面有最新Python教程項目可拿,不懂的問題多跟裏面的人交流,都會解決哦!本文的文字及圖片來源於網絡加上本身的想法,僅供學習、交流使用,不具備任何商業用途,版權歸原做者全部,若有問題請及時聯繫咱們以做處理。

相關文章
相關標籤/搜索