python

时间:2016-05-27 16:28:24

标签: python functional-programming generator

考虑以下简单的生成器:

def simple_gen():
    for number in range(5):
        yield number ** 2

我愿意用itertools.repeatitertools.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模块实现此目的的一些想法?

我不想将生成器强制转换为列表或其他容器。

2 个答案:

答案 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()))