Что выведет этот код?


def generator():
    yield 1
    yield 2
    return 3

gen = generator()
print(next(gen))
print(next(gen))
print(next(gen))

Результат работы кода:

1
2
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
StopIteration

Объяснение:

  • Функция generator() - это генератор.
  • Первые два вызова next(gen) возвращают значения, полученные с помощью yield: 1 и 2.
  • Когда генератор достигает return 3, он завершает свою работу и генерирует исключение StopIteration. Значение 3 игнорируется, так как return в генераторе используется только для сигнализации завершения и, опционально, возврата значения, которое можно получить через атрибут value у исключения StopIteration (начиная с Python 3.7).
  • Третий вызов next(gen) вызывает исключение StopIteration, потому что генератор уже завершил свою работу.

Разбор задачи с генератором в Python

Этот код демонстрирует работу генератора в Python и то, как он обрабатывает оператор return.

Генератор - это особый вид итератора, который позволяет генерировать значения "на лету", не храня всю последовательность в памяти сразу. Ключевое слово yield приостанавливает выполнение функции и возвращает значение. При следующем вызове next(), выполнение функции возобновляется с места, где оно было приостановлено.

Построчное выполнение кода:

  1. def generator():: Определяется функция-генератор с именем generator.
  2. yield 1: При первом вызове next(gen), функция выполнится до этой строки, вернет значение 1 и приостановит свое выполнение.
  3. yield 2: При втором вызове next(gen), выполнение функции возобновится с предыдущей точки останова (после yield 1), выполнится до этой строки, вернет значение 2 и снова приостановится.
  4. return 3: При третьем вызове next(gen), выполнение возобновится после yield 2. Функция выполнит return 3. Оператор return в генераторе, когда после него нет значений для yield, вызывает исключение StopIteration. Значение, возвращаемое return, становится атрибутом value этого исключения (доступно начиная с Python 3.3).
  5. gen = generator(): Создается объект-генератор gen, который еще не начал выполнение.
  6. print(next(gen)): Вызывается next() для генератора. Генератор возвращает 1, которое выводится на экран.
  7. print(next(gen)): Вызывается next() снова. Генератор возвращает 2, которое выводится на экран.
  8. print(next(gen)): Вызывается next() в третий раз. Генератор выполняет return 3 и выбрасывает исключение StopIteration. Так как это исключение не перехвачено, программа завершается с ошибкой.

Результат выполнения (до возникновения ошибки):


1
2
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
StopIteration
  

Важные моменты:

  • Функция-генератор возвращает объект-итератор, а не обычное значение.
  • Ключевое слово yield приостанавливает выполнение функции, сохраняя её состояние.
  • Вызов next() возобновляет выполнение функции с точки останова.
  • return в генераторе прекращает его работу и выбрасывает исключение StopIteration.
  • Начиная с Python 3.3, значение, возвращаемое через return, становится доступным через атрибут value исключения StopIteration. Например:

def generator():
    yield 1
    return 3

gen = generator()
print(next(gen))
try:
    next(gen)
except StopIteration as e:
    print(f"Генератор завершен. Возвращенное значение: {e.value}") # Только в Python 3.3+
0