例如,我們可以在生成器中使用遞回定義斐波那契數列:
from itertools import pairwise
def fibs():
yield 0
yield 1
yield from map(sum, pairwise(fibs()))
for index, result in enumerate(fibs()):
print(index, result)
如果我們嘗試運行它,它會在索引為 1025 時放棄,并在遞回深度超出錯誤的情況下崩潰。下面我復制了輸出的結尾:
1024 4506699633677819813104383235728886049367860596218604830803023149600030645708721396248792609141030396244873266580345011219530209367425581019871067646094200262285202346655868899711089246778413354004103631553925405243
1025 7291993184377412737043195648396979558721167948342308637716205818587400148912186579874409368754354848994831816250311893410648104792440789475340471377366852420526027975140687031196633477605718294523235826853392138525
Traceback (most recent call last):
File "/home/user/área de Trabalho/fibs1.py", line 6, in fibs
yield from map(sum, pairwise(fibs()))
File "/home/user/área de Trabalho/fibs1.py", line 6, in fibs
yield from map(sum, pairwise(fibs()))
File "/home/user/área de Trabalho/fibs1.py", line 6, in fibs
yield from map(sum, pairwise(fibs()))
[Previous line repeated 997 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
現在我們可以嘗試通過用生成器運算式替換 map 來更改它,使其更像 pythonic:
from itertools import pairwise
def fibs():
yield 0
yield 1
yield from (sum(pair) for pair in pairwise(fibs()))
for index, result in enumerate(fibs()):
print(index, result)
現在的問題是,這個版本的運行時間只有第一個版本的一半,在只有 513 的深度內爆并出現更大的錯誤訊息,同時它還回傳最大遞回深度超出錯誤:
512 44893845313309942978077298160660626646181883623886239791269694466661322268805744081870933775586567858979269
513 72639767602615659833415769076743441675530755653534070653184546540063470576806357692953027861477736726533858
Traceback (most recent call last):
File "/home/user/área de Trabalho/fibs2.py", line 6, in <genexpr>
yield from (sum(pair) for pair in pairwise(fibs()))
File "/home/user/área de Trabalho/fibs2.py", line 6, in fibs
(... this repeats a lot, exceeds maximum character limit in SO)
yield from (sum(pair) for pair in pairwise(fibs()))
File "/home/user/área de Trabalho/fibs2.py", line 6, in fibs
yield from (sum(pair) for pair in pairwise(fibs()))
RecursionError: maximum recursion depth exceeded while calling a Python object
所以我問,為什么不同?
我在玩Joel Grus 在他的博客中發布的類似 haskell 的斐波那契實作時注意到了這個問題,但在發布 python 3.10 時將其更改為使用 itertools 模塊中引入的 pairwise。這樣就需要一次匯入(成對),而不是三個匯入(add、islice、tee)和一個輔助函式定義(tail)。
uj5u.com熱心網友回復:
您所指的“耐力”與延遲評估和具有配置的最大堆疊深度的尾遞回有關。
Common Lisp 和 Scheme 之間最大的區別是后者絕對需要適當的尾遞回支持。Lisp 代碼可能能夠永遠回圈,但它保證適合該格式的方案代碼不會增加堆疊。
在 pythonitertools背景關系中,您實際上是在抱怨那不是規范的一部分。而且,以一種或另一種方式表達想法可能會在每次迭代中推動一個或一對堆疊框架。好,可以。您正在測驗的工具不是為符合該要求而撰寫的,當您推動該方面時,它們可能會出現不足。在設計解決方案時,您可能會考慮使用小的lru_cache進行修補,但據我所知,這只是一種學術練習,試圖探索極限,而您已經找到了極限。
代碼正在按照您的要求進行操作。是的,還有設計更好代碼的空間。去吧!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/537098.html
上一篇:如何從嵌套物件中獲取字串陣列
