从自己的输出累加函数

问题描述

我有以下生成器,它有点像 itertools.accumulate,除了它从函数自己的输出获取一个输入,而不是从可迭代对象中获取

def turboaccumulate(f,initial):
    x = initial
    while True:
        x = f(x)
        yield x

标准库中是否包含类似的内容,或者 Python 文档中是否包含推荐的配方?我在大约 20 分钟的搜索中找不到一个

或者,至少:这个操作叫什么?(我高度怀疑“turbo-accumulate”是公认的名称为它。)


本文的背景是努力将 inscrutable lisp behemoth here 解析为凡人可以理解的东西,我归结为:

def blum_blum_shub(p,q,s):
    #assert coprime(p,q)
    M = p * q
    return turboaccumulate(lambda x: pow(x,2,M),s)

然而,最终的函数调用看起来非常愚蠢,所以我想知道它是否存在于标准库中,或者至少有一个更容易识别的名称

解决方法

不幸的是,据我所知,Python 没有这样的内置功能。如果您需要此功能,那么您的生成器函数可能与您所获得的一样干净。

iter 鲜为人知的第二形式几乎可以满足您的需求,但不幸的是,他们使它成为纯粹的副作用,这打破了模式。要使用它,您需要一个与此类似的包装器:

def fp_iter(f,initial):
    acc = initial
    def wrapper():
        nonlocal acc
        return (acc := f(acc))

    return iter(wrapper,object())

>>> i = fp_iter(lambda n: n + 1,0)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3

到那时,我只会使用你的发电机。


就其名称而言,由于我使用 Clojure 的时间,我将其称为 iterate function。这类似于 iteration in math,所以我认为这与您会得到的名称一样合适:

在数学中,迭代可以指迭代一个函数的过程,即重复应用一个函数,使用一次迭代的输出作为下一次迭代的输入。

,

您可以使用 accumulate 以某种非标准方式实现此目的:

from itertools import accumulate,count

def turboaccumulate(f,initial):
    return accumulate(count(),lambda x,y: f(x),initial=initial)

您可以使用任何无限迭代器代替 count,因为它的值会被忽略(从不使用 y)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...