Python:在功能上合并两个迭代器,其中一个迭代器是递归的
Python: Functionally Merging Two Iterators Where One is Recursive
相关问题 How do I merge two python iterators? 适用于两个独立的迭代器。但是,我一直无法找到或想到合并两个迭代器所必需的工具,其中一个迭代器是递归的,并且将另一个迭代器作为输入。我有迭代器 stuff
这是一个简单的列表。然后我有迭代器 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
迭代器使用它的前一个元素作为下一个元素的输入。
表达 theta 的一种优雅方式是使用 more_itertools package:
中可用的 iterate
方法
iterate(lambda theta: update_theta(theta, thing), some_initial_theta)
然而,这样做的问题是 thing
将在整个迭代过程中得到修复。可以通过传入整个列表 stuff
然后 return 来自 update_theta 方法的其余部分来处理这个问题:
iterate(lambda theta: update_theta(theta[0], theta[1]), (some_initial_theta, stuff))
但是,我真的不想修改 update_theta
方法来获取它不感兴趣的整个列表并处理 return 该列表尾部的机制。虽然它在编程上并不困难,但关注点分离很差。 update_theta
不应该知道或关心整个列表 stuff
。
正如 Peter Wood 在评论中所建议的那样,这 正是 内置函数 reduce
的作用:
result = reduce(update_theta, stuff, some_initial_theta)
在 Python 3 中,reduce
已移至 functools.reduce
,因此您需要导入:
from functools import reduce
如果你想要一个所有中间值的迭代器,Python3提供itertools.accumulate
。没有指定初始值的参数,因此您需要将初始值放入迭代器中:
from itertools import accumulate, chain
result_iterator = accumulate(chain([some_initial_theta], stuff), update_theta)
Python 2 没有 itertools.accumulate
,但您可以从 Python 3 文档中复制等效代码。没有简单的方法可以根据 Python 2 标准工具来制定它,这就是人们首先希望将它添加到 Python 3 的原因。
相关问题 How do I merge two python iterators? 适用于两个独立的迭代器。但是,我一直无法找到或想到合并两个迭代器所必需的工具,其中一个迭代器是递归的,并且将另一个迭代器作为输入。我有迭代器 stuff
这是一个简单的列表。然后我有迭代器 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
迭代器使用它的前一个元素作为下一个元素的输入。
表达 theta 的一种优雅方式是使用 more_itertools package:
中可用的iterate
方法
iterate(lambda theta: update_theta(theta, thing), some_initial_theta)
然而,这样做的问题是 thing
将在整个迭代过程中得到修复。可以通过传入整个列表 stuff
然后 return 来自 update_theta 方法的其余部分来处理这个问题:
iterate(lambda theta: update_theta(theta[0], theta[1]), (some_initial_theta, stuff))
但是,我真的不想修改 update_theta
方法来获取它不感兴趣的整个列表并处理 return 该列表尾部的机制。虽然它在编程上并不困难,但关注点分离很差。 update_theta
不应该知道或关心整个列表 stuff
。
正如 Peter Wood 在评论中所建议的那样,这 正是 内置函数 reduce
的作用:
result = reduce(update_theta, stuff, some_initial_theta)
在 Python 3 中,reduce
已移至 functools.reduce
,因此您需要导入:
from functools import reduce
如果你想要一个所有中间值的迭代器,Python3提供itertools.accumulate
。没有指定初始值的参数,因此您需要将初始值放入迭代器中:
from itertools import accumulate, chain
result_iterator = accumulate(chain([some_initial_theta], stuff), update_theta)
Python 2 没有 itertools.accumulate
,但您可以从 Python 3 文档中复制等效代码。没有简单的方法可以根据 Python 2 标准工具来制定它,这就是人们首先希望将它添加到 Python 3 的原因。