[英]Why does Python have a maximum recursion depth?
Python具有最大遞歸深度,但沒有最大迭代深度。 為什么遞歸受限制? 像迭代這樣處理遞歸是不是更自然,而不是限制遞歸調用的數量?
我只想說這個問題的根源來自於嘗試實現一個流(有關流的更多詳細信息,請參閱此問題 )。 例如,假設我們要編寫一個流來生成自然數:
def stream_accum(s, n): # force the stream to a list of length n
def loop(s, acc):
if len(acc) == n:
return acc
hd, tl = s()
return loop(tl, acc + [hd])
return loop(s, [])
def nats():
def loop(n):
return n, lambda: loop(n+1)
return loop(1)
流的遞歸定義非常吸引人。 但是,我想更好/更pythonic的方法是使用發電機。
這里實際上有一些問題。
首先,正如NPE的答案很好地解釋的那樣,Python並沒有消除尾調用,因此許多允許在Scheme中無限遞歸的函數在Python中是有限的。
其次,正如NPE所解釋的那樣,無法消除的調用會占用調用堆棧上的空間。 而且,即使在執行TCE的語言中,也有許多遞歸函數無法像迭代那樣對待。 (考慮遞歸調用自身兩次的天真Fibonacci函數。)
但是為什么調用堆棧首先是有限的資源? Python堆棧幀至少原則上可以在堆上實現並鏈接在一起(請參閱Stackless以獲得該原理的存在證明),並且在64位內存空間中,可以存儲超過1000個堆棧幀。 (實際上,即使是幾乎所有現代平台上的C堆棧都可以容納超過1000個遞歸Python解釋器調用。)
部分原因是歷史性的:股票Python解釋器使用固定的C堆棧在您進行遞歸調用時遞歸調用自身,並且它最初設計用於32位(甚至24位或20位)平台,其中C堆棧非常小。
但這可能已經改變了,Python 3.0將是一個改變它的完美場所。 那么,他們為什么不呢? 因為他們做出了有意識的語言設計決定。 在Pythonic代碼中,遞歸通常非常淺(例如,遍歷淺樹結構的os.walk
代碼); 如果你的功能達到1000附近的任何深度,它更可能是一個錯誤,而不是故意的。 所以,限制仍然存在。 當然這有點循環 - 如果他們刪除了限制(特別是,如果他們消除了尾部調用),更深層次的遞歸將變得更加慣用。 但這就是重點 - 圭多不想要一種語言,其中深度遞歸是慣用的。 (並且大多數Python社區都同意。)
這不是Python獨有的,並且與調用堆棧上的每個調用占用空間有關,並且堆棧的大小是有限的。
單獨迭代不會消耗堆棧空間,因此不受此限制的約束。
並非每個遞歸調用都需要消耗堆棧空間。 例如,某些語言可以自動將尾遞歸轉換為迭代。 但是,CPython選擇不這樣做( Python會優化尾遞歸嗎? )。
您可以通過調用sys.setrecursionlimit
來增加Python調用堆棧的最大深度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.