从自己的输出中累积函数

vaj7vani  于 2021-09-08  发布在  Java
关注(0)|答案(2)|浏览(339)

我有下面的发电机,它有点像 itertools.accumulate ,但它从函数自身的输出而不是iterable获取下一个输入:

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

标准库中是否包含类似的内容,或者python文档中是否包含推荐的方法?我在大约20分钟的搜索中找不到一个。
或者,至少:这个操作叫什么(我非常怀疑“turbo accumulate”是公认的名称。)
这篇文章的背景是试图将难以理解的lisp庞然大物解析成凡人都能理解的东西,我想说的是:

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

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

lf5gs5x2

lf5gs5x21#

不幸的是,据我所知,python并没有这样的内置功能。如果您需要此功能,您的生成器功能可能会尽可能干净。 iter 不太为人所知的第二种形式几乎能满足你的需求,但不幸的是,他们使它完全起到了副作用,这打破了这种模式。要使用它,您需要类似于以下内容的 Package :

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

在这一点上,我会用你的发电机。
它的名字,我知道这是 iterate 由于我使用clojure的时间而导致的函数。这类似于数学中的迭代,所以我认为这是一个合适的名称:
在数学中,迭代可以指迭代函数的过程,即重复应用函数,使用一次迭代的输出作为下一次迭代的输入。

nszi6y05

nszi6y052#

你可以用 accumulate 要以某种非标准方式实现这一点:

from itertools import accumulate, count

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

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

相关问题