Этот вопрос проверяет понимание работы генераторов в Python и различий между ключевыми словами yield и return в одной функции.
В Python функция, содержащая ключевое слово yield, автоматически становится генератором — специальным объектом, который генерирует последовательность значений по запросу, сохраняя своё состояние между вызовами. Ключевое слово return в такой функции имеет особое значение, отличное от его использования в обычных функциях.
Когда интерпретатор встречает yield, выполнение функции приостанавливается, и значение возвращается вызывающему коду. При следующем вызове (например, через next()) выполнение возобновляется с точки после yield. Если в процессе выполнения встречается оператор return, генератор завершается. При этом возникает исключение StopIteration, а значение, указанное после return, становится значением атрибута .value этого исключения.
Рассмотрим генератор, который читает строки из файла до тех пор, пока не встретит строку с определённым маркером, после чего завершается с помощью return.
def read_until_marker(file_path, marker):
"""Генератор, читающий строки файла до маркера."""
with open(file_path, 'r') as file:
for line in file:
if marker in line:
# Завершаем генератор, возвращая количество прочитанных строк
return f"Found marker. Lines read: {count}"
yield line.strip()
count += 1
# Использование
gen = read_until_marker('data.txt', 'STOP')
for line in gen:
print(line)
# После цикла можно получить значение из return, обработав StopIteration
try:
next(gen)
except StopIteration as e:
print(e.value) # Выведет: Found marker. Lines read: Xreturn может сигнализировать об окончании обработки по условию (например, найден искомый элемент) и передавать итоговую метаинформацию.async/await) генераторы с yield использовались для создания корутин. return завершал такую корутину.return — это конечное состояние, после которого генератор больше не может выдавать значения.Вывод: Использовать yield и return в одной функции можно, но это превращает её в генератор. return в данном контексте служит для завершения генератора и передачи финального значения, доступного через исключение StopIteration. Такой подход полезен при создании генераторов, которые должны не только выдавать последовательность элементов, но и сигнализировать о причине своего завершения, возвращая итоговый результат или статус.