Подтвердить что ты не робот

Почему список (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))  # ?!
[]
4b9b3361

Ответ 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 до генерации каких-либо элементов, он выводит пустой список, потому что ничего не было накоплено.