85

在这段代码中,为什么 using 会for导致 noStopIteration 或者for循环捕获所有异常然后静默退出?在这种情况下,为什么我们有多余的return?? 或者是由以下 raise StopIteration原因引起的:return None

#!/usr/bin/python3.1
def countdown(n):
    print("counting down")
    while n >= 9:
        yield n
        n -= 1
    return

for x in countdown(10):
    print(x)

c = countdown(10)
next(c)
next(c)
next(c)

假设StopIteration被触发:return None。什么时候GeneratorExit生成?

def countdown(n):
    print("Counting down from %d" % n)
    try:
        while n > 0:
            yield n
            n = n - 1
    except GeneratorExit:
        print("Only made it to %d" % n)

如果我手动执行:

c = countdown(10)
c.close() #generates GeneratorExit??

在这种情况下,为什么我看不到回溯?

4

1 回答 1

108

for循环StopIteration显式侦听。

for语句的目的是遍历迭代器提供的序列,异常用于表示迭代器现在完成;for不会捕获被迭代的对象引发的其他异常,只是那个异常。

这是因为这StopIteration是一个正常的、预期的信号,它告诉正在迭代的任何人没有更多的东西可以产生。

生成器函数是一种特殊的迭代器;它确实StopIteration在函数完成时引发(即当它返回时,所以是的,return None引发StopIteration)。这是迭代器的要求;他们完成后必须举起StopIteration;事实上,一旦 aStopIteration被引发,试图从它们那里获取另一个元素(通过next(),或在迭代器上调用.next()(py 2) 或.__next__()(py 3) 方法)必须总是再次引发StopIteration

GeneratorExit在另一个方向进行通信是一个例外。您正在使用表达式显式关闭生成器,yieldPython 将该闭包传达给生成器的方式是通过GeneratorExit在该函数内部引发。您在 内部显式捕获该异常countdown,其目的是让生成器在关闭时根据需要清理资源。

AGeneratorExit不会传播给调用者;请参阅generator.close()文档

于 2013-01-19T11:46:14.343 回答