[英]Does Python have an iterative recursion generator function for first-order recurrence relations?
是否有內置函數或標准庫函數大致相當於
def recur_until(start, step_fu, stop_predicate=lambda _: False):
current = start
while not stop_predicate(current):
yield current
current = step_fu(current)
要么
def recur_while(start, step_fu, predicate=lambda _: True):
current = start
while predicate(current):
yield current
current = step_fu(current)
甚至只是
def recur(start, step_fu):
current = start
while True:
yield current
current = step_fu(current)
在任何版本的Python? (當與itertools.takewhile
結合使用時,后者與其他兩個一樣好。)
像這樣的生成器函數將允許迭代地計算某些遞歸定義的序列,即一階遞歸關系。
雖然這些在需要時不太難實現,但我覺得像他們這樣的東西應該是itertools
或者functools
,但如果是的話,我還沒有能夠在文檔中發現它。
list(recur_until(2, lambda x: x**2 - 1, lambda x: x > 1e4))
# [2, 3, 8, 63, 3968]
還應該使用非數字元素:
list(recur_until('', lambda x: '[{}]({})'.format(x, len(x)), lambda x: len(x) > 30))
# ['',
# '[](0)',
# '[[](0)](5)',
# '[[[](0)](5)](10)',
# '[[[[](0)](5)](10)](16)',
# '[[[[[](0)](5)](10)](16)](22)']
在Python 3.3+中,新的itertools.accumulate
可以與其他itertools結合使用
例如:
>>> from itertools import accumulate, repeat, takewhile
>>> fun = accumulate(range(2, 10), lambda x, _: x**2 - 1)
>>> list(fun)
[2, 3, 8, 63, 3968, 15745023, 247905749270528, 61457260521381894004129398783]
>>> fun = takewhile(lambda y: y < 1e4, accumulate(repeat(2), lambda x, _: x**2 - 1))
>>> list(fun)
[2, 3, 8, 63, 3968]
accumulate
接受一個帶有2個參數的序列和函數:第一個是accumulate值,第二個是序列中的下一個值。 在這種情況下,我們只需要第一個參數,這將是傳遞給序列的第一個元素accumulate
的傳遞函數的第一個呼叫,該函數的后續調用的返回值。
因此,我們只需要將傳遞的序列的開頭作為我們的初始值 - 在這種情況下為2
。 序列其余部分的內容是無關緊要的,但我們可以使用它的長度來控制我們想要的元素數量(如第一個示例中所示)或創建無限生成器(如第二個示例)。
缺少的鏈接是你需要一些東西將你的遞歸步進函數轉換成一個生成器。 一旦你有了,那么你可以使用任何itertools方法。
def recur_to_gen(step_fu, current, sentinel=None):
while current != sentinel:
yield current
current = step_fu(current)
matches = itertools.takewhile(predicate, recur_to_gen(step_fu, start))
recur_to_gen
可能是一個合理的建議添加到itertools
。
功能包提供了模擬這一點的部分。
from functional import dropWhile, iterate
recur = dropWhile(predicate, iterate(step_func, start))
例如,
>>> next(dropWhile(lambda x : x < 10, iterate(lambda x: x + 1, 2)))
10
( dropWhile
與itertools.dropwhile
沒有什么不同。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.