Python:在功能上合并两个迭代器,其中一个是递归的

Python:在功能上合并两个迭代器,其中一个是递归的,python,recursion,functional-programming,iterator,generator,Python,Recursion,Functional Programming,Iterator,Generator,相关的问题对于两个独立的迭代器很有效。然而,我还没有找到或想到合并两个迭代器所需的工具,其中一个是递归的,另一个作为输入。我有迭代器东西,这是一个简单的列表。然后我有迭代器theta,它接受一个函数func,并产生x,func(x),func(func(x)),其中func的一个输入是stuff的一个元素。我用可变状态解决了这个问题,如下所示: theta = some_initial_theta for thing in stuff: theta = update_theta(thet

相关的问题对于两个独立的迭代器很有效。然而,我还没有找到或想到合并两个迭代器所需的工具,其中一个是递归的,另一个作为输入。我有迭代器
东西
,这是一个简单的列表。然后我有迭代器
theta
,它接受一个函数
func
,并产生x,func(x),func(func(x)),其中
func
的一个输入是
stuff
的一个元素。我用可变状态解决了这个问题,如下所示:

theta = some_initial_theta
for thing in stuff:
    theta = update_theta(theta, thing)
return theta
这种格式的一个具体示例:

def update_theta(theta, thing):
    return thing * 2 + theta

stuff = [100, 200, 300, 400]


def my_iteration():
    theta = 0
    for thing in stuff:
        theta = update_theta(theta, thing)
    print(theta)
# This prints 2000
我相信有一种优雅的方法可以做到这一点,而不需要可变状态和for循环。一个简单的zip对我来说不起作用,因为
theta
迭代器使用它的前一个元素作为下一个元素的输入

表示θ的一种优雅方式是使用
iterate
方法,该方法可在以下目录中找到:

然而,问题是,
东西
将在整个迭代过程中得到修复。可以通过传入整个列表
stuff
来处理此问题,然后从update_theta方法返回剩余部分:

iterate(lambda theta: update_theta(theta[0], theta[1]), (some_initial_theta, stuff))

然而,我真的不想修改
update_theta
方法来获取它不感兴趣的整个列表,并处理返回该列表尾部的机制。虽然在编程上并不困难,但是关注点的分离很差
update_theta
不应该知道或关心整个列表
内容

正如Peter Wood在评论中所建议的那样,这正是内置函数的作用:

在Python 3中,
reduce
已移动到,因此您需要导入:

from functools import reduce
如果需要所有中间值的迭代器,Python 3提供了
itertools.accumulate
。没有参数指定初始值,因此需要将初始值放入迭代器:

from itertools import accumulate, chain
result_iterator = accumulate(chain([some_initial_theta], stuff), update_theta)

Python2没有
itertools.accumulate
,但是您可以从Python3文档中复制等效的代码。用Python 2标准工具来表述它并不容易,这就是为什么人们首先希望将它添加到Python 3中。

您能否提供一个简单的自包含示例来说明您所说的内容(例如,简单迭代器的实际示例,其行为与您描述的方式相同)?@BrenBarn我添加了一个具体的例子。请看@PeterWood,在reduce的每一步中,你将如何处理列表中的一个新元素
stuff
。另外,从您的示例来看,您似乎试图将两个迭代器组合在一起以获得单个结果(而不是中间结果的iterable),这与您链接到的问题有所不同,这意味着在获得该结果的过程中,所进行的操作的细节可能不那么重要。谢谢!我需要进一步测试
减少
。我想,让我之前被
reduce
绊倒的是,它只处理2个参数。就像x+y中的x和y一样,而我的update_theta()接受许多参数。我想我需要做的是定义一个lambda,它保持所有其他参数不变,然后简单地将它与reduce一起使用,就像一个单参数函数一样。回到这个问题上我一直很慢,但我相信你的解决方案是正确的,所以我会继续给你评分。我只需要使用一个lambda,将它简化为两个参数。
from functools import reduce
from itertools import accumulate, chain
result_iterator = accumulate(chain([some_initial_theta], stuff), update_theta)