0

我无法想象我是第一个写这样一个类的人:

class RestartableGenerator:
    def __init__(self, g):
        self.g = g
    def __iter__(self):
        return self.g().__iter__()

if __name__=='__main__':
    def gen():
        print 'Generating'
        for i in range(5):
            yield i
    i = RestartableGenerator(gen)
    print 'Using'
    print list(i)
    print list(i)

测试产生以下输出:

Using
Generating
[0, 1, 2, 3, 4]
Generating
[0, 1, 2, 3, 4]

但我没有在标准库中找到它。我查看了 itertools 和 functools。

真的没有吗?如果是,在哪里?

它是否被认为是不必要的,因为当你想多次评估一个序列时,你最好将它存储在一个列表中?

编辑1:我的用例是我希望它对于消费者来说是透明的,由于内存消耗的原因,序列是生成器而不是列表。

编辑2:如果标准库中没有这样的类,你认为什么名字合适?括号去除器?多次迭代?还要别的吗?为什么?

4

2 回答 2

2

从回到序列开头的意义上说,这并不是完全可以重新启动的。每次__iter__调用都会创建一个新的生成器,它将重新运行生成器代码,可能会重新执行副作用并产生不同的结果。如果您想在生成的序列上使用独立的迭代器,那就是listoritertools.tee的用途。否则,再次显式调用生成器函数会更清楚,所以这不是很有用。您以不那么明确、更容易出错的代码为代价节省了一对括号。

请注意,如果您想要一个惰性序列类型,迭代它会动态生成元素,但您可以重复迭代它,您应该将其__iter__方法定义为生成器:

class Primes(object):
    def __iter__(self):
        for i in itertools.count():
            if is_prime(i):
                yield i

这不是“可重新启动的生成器”,但听起来像你想要的。

于 2013-08-22T20:54:57.953 回答
2

你可以稍微简化一下:

class RestartableGenerator:
    def __init__(self, g):
        self.g = g
    def __iter__(self):
        return self.g()

调用gen()返回一个生成器对象。生成器对象有一个next方法,它是__iter__必须返回的对象。

然而,没有必要RestartableGenerator,因为它没有做任何gen自己不能做的事情。与其保持gen类属性,不如保持gen自身。

def gen():
    print 'Generating'
    for i in range(5):
        yield i

print 'Using'
print list(gen())
print list(gen())
于 2013-08-22T20:50:46.033 回答