为什么接下来会提出'StopIteration',但'for'会做出正常的回报?

59 python iterator generator stopiteration

在这段代码中,为什么使用'for'会导致没有'StopIteration'或'for'循环捕获所有异常然后以静默方式退出?在这种情况下,为什么我们有无关的"回归"?或者是 for由:StopIteration

#!/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)
Run Code Online (Sandbox Code Playgroud)

假设for是由以下方式触发:return.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)
Run Code Online (Sandbox Code Playgroud)

如果我手动执行:

c = countdown(10)
c.close() #generates GeneratorExit??
Run Code Online (Sandbox Code Playgroud)

在哪种情况下,为什么我看不到追溯?

Mar*_*ers 81

for循环监听StopIteration明确.

for语句的目的是循环迭代器提供的序列,异常用于表示迭代器现在已完成; for没有捕获被迭代的对象引发的其他异常,只是那个.

那是因为StopIteration正常的,预期的信号告诉任何人正在迭代,没有什么可以产生的.

生成器函数是一种特殊的迭代器; 它确实StopIteration在函数完成时引发(即当它返回时,所以是的,return None引发StopIteration).这是迭代器的要求; 他们必须StopIteration在完成时加注; 事实上,一旦StopIteration提高了,试图从他们那里得到另一个元素(通过next(),或致电.next()(PY 2)或.__next__()对迭代器(PY 3)方法)必须始终提高StopIteration一次.

GeneratorExit另一个方向沟通是一个例外.您正在使用表达式显式关闭生成器yield,并且Python将该闭包传递给生成器的方式是通过提升GeneratorExit该函数的内部.您明确地捕获了该异常countdown,其目的是让生成器在关闭时根据需要清理资源.

A GeneratorExit不会传播给调用者; 看generator.close()文档.

  • 如果找不到匹配项,可以通过为 next() 提供默认值来避免 StopIteration,例如 next(generator_expression, None)。 (20认同)
  • 另请注意,for only只会在评估迭代器时捕获异常.如果它在for循环体内升起,它将无法捕获它. (5认同)