为什么嵌套的空生成器提前退出而不会引发错误?

问题描述 投票:2回答:2

我正面临着嵌套generators的奇怪行为。

def empty_generator():
    for i in []:
        yield

def gen():
    next(empty_generator())
    print("This is not printed, why?")
    yield

list(gen())  # No Error

next(empty_generator())  # Error

我希望gen()函数引发错误,因为我在空发生器周围调用next()。但事实并非如此,这些功能无处不在,无需提升或打印任何东西。

这似乎违反了最不惊讶的原则,不是吗?

python python-3.x generator
2个回答
2
投票

从技术上讲,你没有错误;你有一个未被捕获的StopIteration异常,用于流量控制。对list的调用采用任意迭代作为其参数,捕获了gen为您提出的异常。

for循环工作类似;每个迭代器最后都会引发StopIteration,但是for循环捕获它并以响应结束。

换句话说,迭代的消费者负责捕捉StopIteration。当gen调用next时,它会让异常冒泡。对list的调用捕获了它,但是当你明确地调用next时却没有。


请注意,PEP-479会更改此行为。 Python 3.5通过__future__提供了新的语义,Python 3.6提供了弃用警告,Python 3.7(2018年夏季到期)完成了转换。我将读者引用到PEP本身以获取更多详细信息。


1
投票

一旦迭代器到达它的末尾,它就会引发StopIteration ......停止迭代,所以list(gen())构造一个空列表。

© www.soinside.com 2019 - 2024. All rights reserved.