使用递归函数itertools
我需要一个Python函数iterate(f, x)
创建一个迭代器返回值x,f(x),f(f(x)),f(f(f(x)))等(如,例如,Clojure's iterate
)。首先,我想知道:这是否已经存在于标准库的某个地方,我只是想念它?当然,这是很容易与发电机来实现:使用递归函数itertools
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))
,但看起来像一个虐待我。我能更好地做到这一点吗?
itertools似乎没有什么能够做到你想要的,但itertools是一个深藏宝箱,所以我可能错过了一些东西。
您的生成器代码看起来不错。我不知道你为什么要用积累来写它,除非你打了一场荒谬的高尔夫比赛,或者你想让Haskell势不可挡。编写你的函数,使其可读,可理解和可维护。不需要太聪明。
你是对的,在写这篇文章之前,我甚至都没有想过这个奇怪的“累积”版本。我真的很想知道我是否错过了使用itertools的一个很好,简洁的方法。 我发现自己将函数转换为迭代器(像这里或[itertools recipes]中的'tabulate'示例(http:// docs。python.org/2/library/itertools.html#recipes)时不时想知道什么是最Python的方式来做到这一点。 – embee 2013-03-26 12:26:03
您可以使用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)
我喜欢这个。有趣的是,这个'unfold'的构造与我原来的'iterate'生成器完全一样,但是获得了全新的抽象层次和通用性,因为f现在返回对而不是单个值。尼斯。 – embee 2013-03-27 19:11:10
我会说'累加()'版本就好了。 *两个*版本都很好。 – 2013-03-26 12:07:15
对于'accumulate()'版本,我真的觉得很奇怪,因为对于计算来说,x只需要* once *作为种子,所以需要'repeat(x)'或类似的东西。 – embee 2013-03-26 12:36:03
@embee现在你提到它了,我也觉得很奇怪。作为第一个解决方案最好的问题 – jamylak 2013-03-26 12:38:54