【问题标题】:Using itertools for recursive function application使用 itertools 进行递归函数应用
【发布时间】:2013-03-16 05:23:45
【问题描述】:

我需要一个 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))

但对我来说似乎是一种虐待。我可以做得更好吗?

【问题讨论】:

  • 我会说accumulate() 版本很好。 两个版本都很好。
  • 我对@9​​87654328@ 版本真正感到奇怪的是需要repeat(x) 或类似的东西,因为x 实际上只需要一次 作为计算的种子.
  • @embee 既然你提到了它,我也觉得这很奇怪。 Prob best 作为第一个解决方案
  • 作为@Ned 提到的Haskell 势利小人之一,我想说的是,有一种从单个 初始值生成iterate 的好方法:通过使用anamorphism(本质上与reduce相反)。
  • 这基本上就是我要找的东西,@phg,这就是我使用“递归”这个词的原因。但是你会如何用 Python 来表达呢?

标签: python functional-programming iterator generator itertools


【解决方案1】:

itertools 中似乎没有什么可以满足您的需求,但 itertools 是一个很深的宝箱,所以我可能错过了一些东西。

您的生成器代码看起来很棒。我不知道为什么你会用累积来写它,除非你在玩一个荒谬的代码高尔夫游戏,或者你想给 Haskell 势利小人留下深刻印象。编写您的函数,使其具有可读性、可理解性和可维护性。不需要太聪明。

【讨论】:

  • 你说得对,在写这篇文章之前,我什至不会想到奇怪的accumulate 版本。我真的想知道我是否错过了一种使用 itertools 的简洁的好方法。我发现自己不时将函数转换为迭代器(例如此处或 itertools recipes 中的 tabulate 示例,并且想知道最 Pythonic 的方法是什么。
【解决方案2】:

您可以使用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

ana 实现iterate 然后看起来像这样:

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 现在返回对而不是单个值,因此获得了全新的抽象水平和通用性。不错。
猜你喜欢
  • 2020-09-09
  • 2012-09-07
  • 1970-01-01
  • 2020-11-22
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
相关资源
最近更新 更多