从迭代器返回然后抛出StopIteration

时间:2012-02-22 18:47:16

标签: python iterator stopiteration

当迭代器耗尽时,从迭代器返回一些东西的好方法是什么?我正在使用旗帜,但这很难看:

class Example():

    def __iter__(self):
        self.lst = [1,2,3]
        self.stop = False # <-- ugly            
        return self

    def next(self):
        if self.stop:  # <-- ugly
            raise StopIteration
        if len(self.lst) == 0:
            self.stop = True            
            return "one last time"
        return self.lst.pop()

背景:我从外部源获取未知数量的字符串,然后将它们进一步发送给调用者。当进程结束时,我想发出一个字符串“x records processed”。我无法控制调用代码,因此必须在迭代器中完成。

4 个答案:

答案 0 :(得分:6)

你可以从__iter__屈服,这会把它变成一个生成器函数(或者你可以按照Dan的建议写一个生成器函数)。正如警告一样,这可能会误导滥用next方法的人。

class Example():

    def __iter__(self):
        lst = [1,2,3]
        for i in reversed(lst):
            yield i
        yield "one last time"

答案 1 :(得分:5)

也许您可以使用生成器功能:

def example():
    lst = [1, 2, 3]
    while lst:
        yield lst.pop()
    yield 'one last time'

答案 2 :(得分:1)

不要再回复一件事。这是个坏主意,因为它不能很好地延伸。如果你想要总和以及计数怎么办?或哈希以及计数?迭代器是一个有状态的对象。利用它。

class Example( collections.Iterator ):
    def __iter__(self):
        self.lst = [1,2,3]
        self.count = 0       
        return self
    def next(self):
        if self.lst:
            self.count += 1
            return self.lst.pop()
        raise StopIteration()

像这样使用它。

my_iter= iter(Example())
for item in my_iterprin:
    print( item )

print( my_iter.count )

答案 3 :(得分:0)

你可以这样做:

class Example():
    def __iter__(self):
        self.lst = [1, 2, 3]
        return self

    def next(self):
        try:
            return self.lst.pop()
        except IndexError:
            print "done iterating"
            raise StopIteration

>>> for i in Example():
...   print i
...
3
2
1
done iterating

在您的实际代码中,您可能需要更改正在捕获的异常类型,但此格式仍然适用。