Почему список (next (iter (())) для _ в диапазоне (1)) == []?
Почему 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)) # ?!
[]
Ответы
Ответ 1
при условии, что все идет хорошо, понимание генератора x() for _ in range(1)
должно поднять StopIteration
, когда оно закончено, итерации над range(1)
, чтобы указать, что в список больше нет элементов для упаковки.
Однако, поскольку x()
повышает значение StopIteration
, он заканчивается с раннего значения, это поведение является ошибкой в python, который обрабатывается с помощью PEP 479
В python 3.6 или с помощью from __future__ import generator_stop
в python 3.5, когда 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
Ответ 2
Исключение StopIteration
используется, чтобы сообщить базовому механизму функции list
когда фактически следует прекратить итерацию для передаваемого ему итерируемого. В вашем случае вы говорите Python, что вещь, которая была передана в list()
является генератором. Поэтому, когда генератор StopIteration
до генерации каких-либо элементов, он выводит пустой список, потому что ничего не было накоплено.