为什么list(next(iter(())) for _ in range(1))
会返回空列表而不是提出StopIteration
?
>>> next(iter(()))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> [next(iter(())) for _ in range(1)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> list(next(iter(())) for _ in range(1)) # ?!
[]
同样的事情发生在明确提出StopIteration
的自定义函数中:
>>> def x():
... raise StopIteration
...
>>> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
StopIteration
>>> [x() for _ in range(1)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
StopIteration
>>> list(x() for _ in range(1)) # ?!
[]
答案 0 :(得分:10)
假设一切顺利,生成器理解x() for _ in range(1)
在完成迭代StopIteration
时应该引发range(1)
,表示没有更多项可以打包到列表中。
但是因为x()
引发StopIteration
它最终会退出,这意味着此行为是python中的一个错误,正在使用PEP 479
在python 3.6中或在python 3.5中使用from __future__ import generator_stop
当StopIteration传播得更远时,它会转换为RuntimeError
,以便list
不会将其注册为结尾理解。当这有效时,错误如下所示:
Traceback (most recent call last):
File "/Users/Tadhg/Documents/codes/test.py", line 6, in <genexpr>
stuff = list(x() for _ in range(1))
File "/Users/Tadhg/Documents/codes/test.py", line 4, in x
raise StopIteration
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Tadhg/Documents/codes/test.py", line 6, in <module>
stuff = list(x() for _ in range(1))
RuntimeError: generator raised StopIteration
答案 1 :(得分:7)
StopIteration
异常用于告诉list
函数的基本机制何时实际停止迭代已传递给它的迭代。在你的情况下,你告诉Python,传递给list()
的东西是一个生成器。因此,当生成器在生成任何项目之前抛出StopIteration
时,它会输出一个空列表,因为没有积累任何内容。