为什么在范围(1)中_的列表(next(iter(()))== []?

时间:2016-08-29 20:49:16

标签: python for-loop iterator

为什么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))  # ?!
[]

2 个答案:

答案 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时,它会输出一个空列表,因为没有积累任何内容。