我需要一个Python函数iterate(f, x)
,它创建一个迭代器,返回值x,f(x),f(f(x)),f(f(f(x)))等(如,例如,Clojure's iterate
)。首先,我想知道:这是否已经存在于标准库的某个地方,我只是错过了它?当然,使用生成器实现起来很容易:
def iterate(f, x):
while True:
yield x
x = f(x)
出于好奇:在Python中是否有更实用的方法,例如用一些itertools或functools魔法?
在Python 3.3中,这将起作用
def iterate(f, x):
return accumulate(repeat(x), lambda acc, _ : f(acc))
但对我来说似乎是一种虐待。我可以更好地做到这一点吗?
答案 0 :(得分:5)
在itertools中似乎没有什么可以做你想要的东西,但是itertools是一个很深的宝库,所以我可能错过了一些东西。
您的生成器代码看起来很棒。我不知道你为什么要用累积来写它,除非你正在玩一个荒谬的代码高尔夫游戏,或者你试图打动Haskell势利小人。编写您的函数,使其可读,易懂和易于维护。不需要过于聪明。
答案 1 :(得分:3)
您可以使用anamorphism(或展开)来简化iterate
的定义,并仅使用一个起始值。这是我曾经使用的一个实现,基于一个非常着名的paper:
def ana(build, predicate):
def h(x):
if predicate(x):
return
else:
a, b = build(x)
yield a
for i in h(b):
yield i
# with newer syntax:
# yield from h(b)
return h
使用iterate
实施ana
,然后如下所示:
def iterate(f, x):
return ana(lambda x: (x, f(x)), lambda _: False)(x)
没有itertools,但是......我同意这不是最易读的变体。事实上,这是相当神秘的。
更新:有一个更简单的版本,甚至看起来很不错。它来自here:
def unfold(f, x):
while True:
w, x = f(x)
yield w
这会给你:
def iterate(f, x):
return unfold(lambda y: (y, f(y)), x)