如何将元组的Python生成器拆分为两个独立的生成器?

如何将元组的Python生成器拆分为两个独立的生成器?,python,generator,Python,Generator,我有一个发电机,大致如下: def gen1(): for x, y in enumerate(xrange(20)): a = 5*x b = 10*y yield a, b for a in gen1_split_a(): yield a for b in gen1_split_b(): yield b 从这个生成器中,我想创建两个单独的生成器,如下所示: def gen1(): for x, y in e

我有一个发电机,大致如下:

def gen1():
    for x, y in enumerate(xrange(20)):
        a = 5*x
        b = 10*y
        yield a, b
for a in gen1_split_a():
    yield a

for b in gen1_split_b():
    yield b
从这个生成器中,我想创建两个单独的生成器,如下所示:

def gen1():
    for x, y in enumerate(xrange(20)):
        a = 5*x
        b = 10*y
        yield a, b
for a in gen1_split_a():
    yield a

for b in gen1_split_b():
    yield b

我的工作是什么,SA?

你不能,除非你最终保持所有生成器输出,以便在第二个循环中生成
b
值。这在内存方面可能会很昂贵

您将使用“复制”生成器:

from itertools import tee

def split_gen(gen):
    gen_a, gen_b = tee(gen, 2)
    return (a for a, b in gen_a), (b for a, b in gen_b)

gen1_split_a, gen1_split_b = split_gen(gen1)

for a in gen1_split_a:
    print a

for b in gen1_split_b:
    print b
但是在这种情况下,
tee
对象将不得不存储
gen1
生成的所有内容。从文件中:

此itertool可能需要大量辅助存储(取决于需要存储的临时数据量)。通常,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,那么使用
list()
而不是
tee()
会更快

按照该建议,只需将
b
值放入第二个循环的列表中:

b_values = []
for a, b in gen1():
    print a
    b_values.append(a)

for b in b_values:
    print b

或者更好的方法是,在一个循环中同时处理
a
b

我有一个解决方案,可能不是您想要的。它将
n
-元组生成器分离为
n
单个生成器的元组但是,它要求返回当前元组的每个单独值以继续下一个元组。严格地说,它将一个
n
-元组生成器“拆分”为
n
生成器,但您的示例不会像前面介绍的那样工作。

它利用Python将值发送回生成器以影响未来收益率的能力。同样的想法也应该可以用类来实现,但我还是想掌握生成器

初始化新生成器时,它们只知道当前的
n
-元组。每次它们在各自的索引中生成值时,都会执行回调,将此索引通知给更高级别的生成器。一旦生成了当前元组的所有索引,更高级别的生成器将移动到下一个元组并重复该过程

这可能有点笨拙,但下面是代码(Python3.6)


triple()
是一个三元组生成器,
split_iterator()
生成三个生成器,每个生成器从
triple()
生成的元组中生成一个索引。每个
\u sub\u迭代器
仅在当前元组中的所有值都已生成后才能进行处理。

您可以在gen1()中对a,b执行
,但如果您需要所有
a
,则所有
b
我建议进行完整的重组;使用生成器没有任何意义,因为您需要预先获得所有对。您只需运行生成器两次,每次只使用两个元素中的一个。为什么不直接执行
gen=gen1()
def gen_bs(gen):对于gen中的b:产生b[1]
?,然后
gen_bs(gen)
?谢谢Martijn!前者成功了。也就是说,我做了一些重构,并从代码中完全忽略了这一点。不过,我还是把它保存在我的笔记里,以备下次使用!