我面临着嵌套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()
。但事实并非如此,这些功能无处不在,无需提升或打印任何东西。
这似乎违反了最不惊讶的原则,不是吗?
答案 0 :(得分:2)
从技术上讲,你没有错误;你有一个未被捕获的StopIteration
异常,它用于流量控制。对list
的调用(以任意可迭代为参数)捕获gen
为您引发的异常。
for
循环类似;每个迭代器最后都会引发StopIteration
,但for
循环捕获它并以响应结束。
换句话说,iterable的使用者负责捕获StopIteration
。当gen
调用next
时,它会让异常冒泡。拨打list
的电话会抓住它,但是当您明确致电next
时,您就不会接听。
请注意,PEP-479会更改此行为。 Python 3.5通过__future__
提供了新的语义,Python 3.6提供了弃用警告,Python 3.7(2018年夏季到期)完成了转换。我将读者引用到PEP本身以获取更多详细信息。
答案 1 :(得分:1)
一旦迭代器到达终点,它就会引发StopIteration
......停止迭代,所以list(gen())
构造一个空列表。