考虑以下简单的生成器:
def simple_gen():
for number in range(5):
yield number ** 2
我愿意用itertools.repeat
和itertools.chain
将发生器连接n次。为清楚起见,请考虑以下(非生成器)示例:
array = [1,2,3,4]
repetitions = itertools.repeat( array ,2)
list(itertools.chain.from_iterable(repetitions)) -> [1,2,3,4,1,2,3,4]
我想要相同但使用我自己的生成器(simple_gen)而不是数组。当然,简单的替换不起作用,因为itertools.repeat
重复相同的对象,因此生成器的后续重复将被用尽。
有关如何使用itertools模块实现此目的的一些想法?
我不想将生成器强制转换为列表或其他容器。
答案 0 :(得分:4)
您可以先将生成器输出转换为列表:
repeat(list(simple_gen()), 2)
你不能否则重复生成器输出。最多可以重新生成生成器 count 次数:
from itertools import repeat
def recreate(callable, count=None):
for c in repeat(callable, count):
yield from c()
在Python 3和
中from itertools import repeat
def recreate(callable, count=None):
for c in repeat(callable, count):
for val in c():
yield val
用于Python 2并使用它而不是chain.from_iterable(repeat(callable(), count))
。请注意,生成器函数未调用,而是传入函数对象本身。
演示:
>>> from itertools import repeat
>>> def simple_gen():
... for number in range(5):
... yield number ** 2
...
>>> def recreate(callable, count=None):
... for c in repeat(callable, count):
... for val in c():
... yield val
...
>>> list(recreate(simple_gen, 2))
[0, 1, 4, 9, 16, 0, 1, 4, 9, 16]
答案 1 :(得分:2)
装饰师怎么样:
from itertools import repeat
class repeat_gen:
def __init__(self, count):
self.count = count
def __call__(self, gen):
for it in repeat(gen, self.count):
yield from it()
@repeat_gen(3)
def simple_gen():
for number in range(5):
yield number ** 2
print(list(simple_gen))
请注意,没有itertools.repeat
的以下内容也适用。由于simple_gen
作为泛型函数传递给装饰器,因此可以多次调用它。
class repeat_gen:
def __init__(self, count):
self.count = count
def __call__(self, gen):
self.gen = gen
def repeat_gen():
for i in range(self.count):
yield from self.gen()
return repeat_gen
@repeat_gen(3)
def simple_gen():
for number in range(5):
yield number ** 2
print(list(simple_gen()))