Генераторы — это специальные итерируемые объекты в Python, которые позволяют создавать последовательности "на лету", не занимая память под всю коллекцию сразу. Они реализуются с помощью функций с ключевым словом yield или генераторных выражений ((expr for ... in ...)). Это удобно при работе с большими объёмами данных или потенциально бесконечными потоками.
Ключевые отличия от списковых выражений:
[x for x in range(10)]) создают сразу весь список в памяти.(x for x in range(10))) создают элементы по одному, потребляя гораздо меньше памяти.Когда использовать генераторы:
# Генераторная функция def counter(n): for i in range(n): yield i for number in counter(5): print(number)
"В чём разница между использованием функции с yield и обычной функцией, возвращающей список? Приведите пример."
Ответ:
Обычная функция сразу вычисляет и возвращает список, занимая память под все его элементы. Функция с yield возвращает генератор, который выдаёт элементы по одному и не загружает в память всю последовательность сразу.
def make_list(n): return [i for i in range(n)] # Вернёт список сразу, занимает много памяти def make_generator(n): for i in range(n): yield i # Будет выдавать по одному элементу
История
В проекте для анализа больших логов использовались списковые выражения для выделения строк, содержащих ошибки:
error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]
Файл превышал 2 ГБ и приложение вылетело с OOM (Out of Memory). Нужно было использовать генератор:
error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)
История
Сотрудник хотел проанализировать короткий список, писал функцию с yield, но забыл, что возвращается генератор, а не список:
result = my_generator_function() # result — генератор, а не список if len(result) > 5: # TypeError: object of type 'generator' has no len()
Исправление: обернуть результат в list().
История
Пытались итерироваться по генератору несколько раз:
numbers = (i for i in range(5)) for n in numbers: pass # исчерпали генератор for n in numbers: print(n) # ничего не выводит
Генератор — одноразовый. Нужно создавать новый для повторного использования.