目标是使用 iter
builtin
函数同时对 parallel 中的单个sum & map
进行计算< / strong>即可。也许使用(例如)itertools
而不是经典for loops
来分析通过iterator
...
在一个简单的示例案例中,我想计算ilen, sum_x & sum_x_sq
:
ilen,sum_x,sum_x_sq=iterlen(iter),sum(iter),sum(map(lambda x:x*x, iter))
但未将(大) iter
转换为list
(与iter=list(iter)
一样)
n.b。使用sum & map
和不使用for loops
执行此操作,可能使用itertools
和/或threading
模块?
def example_large_data(n=100000000, mean=0, std_dev=1):
for i in range(n): yield random.gauss(mean,std_dev)
- 编辑 -
非常具体:我正在好好看看itertools
,希望有一个像map
这样的双重功能可以做到这一点。例如:len_x,sum_x,sum_x_sq=itertools.iterfork(iter_x,iterlen,sum,sum_sq)
如果我非常具体:我正在寻找一个答案,&#34; iterfork
&#34;的python源代码。过程
答案 0 :(得分:2)
您可以使用itertools.tee
将单个迭代器转换为三个迭代器,您可以将它们传递给三个函数。
iter0, iter1, iter2 = itertools.tee(input_iter, 3)
ilen, sum_x, sum_x_sq = count(iter0),sum(iter1),sum(map(lambda x:x*x, iter2))
将工作,但内置函数sum
(以及Python 2中的map
)并未以支持并行迭代的方式实现。您调用的第一个函数将完全使用其迭代器,然后第二个函数将使用第二个迭代器,然后第三个函数将使用第三个迭代器。由于tee
必须存储其输出迭代器之一所看到的值,而不是所有其他输出迭代器,这与从迭代器创建列表并将其传递给每个函数基本相同。
现在,如果您使用生成器函数,它们输出的每个值只消耗其输入中的单个值,您可以使用zip
进行并行迭代。在Python 3中,map
和zip
都是生成器。问题是如何将sum
变成生成器。
我认为你可以使用itertools.accumulate
(在Python 3.2中添加)来获得你想要的东西。它是一个生成器,可以生成其输入的运行总和。以下是您如何使其适用于您的问题(我假设您的count
函数应该是len
的迭代器友好版本):
iter0, iter1, iter2 = itertools.tee(input_iter, 3)
len_gen = itertools.accumulate(map(lambda x: 1, iter0))
sum_gen = itertools.accumulate(iter1)
sum_sq_gen = itertools.accumulate(map(lambda x: x*x, iter2))
parallel_gen = zip(len_gen, sum_gen, sum_sq_gen) # zip is a generator in Python 3
for ilen, sum_x, sum_x_sq in parallel_gen:
pass # the generators do all the work, so there's nothing for us to do here
# ilen_x, sum_x, sum_x_sq have the right values here!
如果您使用的是Python 2而不是3,那么您必须编写自己的accumulate
生成器函数(在我上面链接的文档中有纯Python实现) ,并使用itertools.imap
和itertools.izip
而非内置map
和zip
函数。