Python Генераторы
Генераторы в Python — это особый тип итераторов, которые позволяют создавать последовательности значений по требованию, не сохраняя их все в памяти одновременно. Генераторы реализуют ленивое вычисление и являются мощным инструментом для работы с большими данными.
Способы создания генераторов
- Generator functions — функции с yield
- Generator expressions — генераторные выражения
- Generator classes — классы с __iter__ и __next__
Пример функции-генератора
Генераторные выражения
1# Генераторное выражение
2squares = (x**2 for x in range(10))
3
4# Эквивалентная функция-генератор
5def squares_func():
6 for x in range(10):
7 yield x**2
8
9# Использование
10for square in squares:
11 print(square)
12
13# Генераторы можно использовать в функциях
14sum_of_squares = sum(x**2 for x in range(10))
15print(sum_of_squares) # 285
Преимущества генераторов
- Память — экономят память, создавая значения по требованию
- Производительность — ленивое вычисление
- Бесконечные последовательности — могут создавать бесконечные итерации
- Композиция — легко комбинировать с другими генераторами
Пример бесконечного генератора
1def fibonacci():
2 a, b = 0, 1
3 while True:
4 yield a
5 a, b = b, a + b
6
7# Получение первых 10 чисел Фибоначчи
8fib = fibonacci()
9for i in range(10):
10 print(next(fib))
11
12# Или с помощью itertools
13import itertools
14fib_numbers = list(itertools.islice(fibonacci(), 10))
15print(fib_numbers)
Методы генераторов
1def my_generator():
2 try:
3 value = yield "Первое значение"
4 yield f"Получено: {value}"
5 except GeneratorExit:
6 print("Генератор закрывается")
7 except Exception as e:
8 print(f"Получено исключение: {e}")
9
10gen = my_generator()
11print(next(gen)) # Первое значение
12
13# send() - отправка значения в генератор
14print(gen.send("Привет")) # Получено: Привет
15
16# throw() - отправка исключения
17gen = my_generator()
18next(gen)
19gen.throw(ValueError("Ошибка"))
20
21# close() - закрытие генератора
22gen = my_generator()
23next(gen)
24gen.close()
Практические примеры
1# Чтение больших файлов
2def read_large_file(file_path):
3 with open(file_path, 'r') as file:
4 for line in file:
5 yield line.strip()
6
7# Фильтрация данных
8def filter_even_numbers(numbers):
9 for num in numbers:
10 if num % 2 == 0:
11 yield num
12
13# Pipeline обработки данных
14def process_data(data):
15 for item in data:
16 # Обработка каждого элемента
17 processed = item.upper()
18 yield processed
19
20# Использование pipeline
21numbers = range(1, 11)
22even_numbers = filter_even_numbers(numbers)
23processed_data = process_data(str(n) for n in even_numbers)
24
25for item in processed_data:
26 print(item) # 2, 4, 6, 8, 10
Генераторы vs Списки
1import sys
2
3# List comprehension - создает весь список в памяти
4squares_list = [x**2 for x in range(1000000)]
5print(f"Размер списка: {sys.getsizeof(squares_list)} байт")
6
7# Generator expression - создает генератор
8squares_gen = (x**2 for x in range(1000000))
9print(f"Размер генератора: {sys.getsizeof(squares_gen)} байт")
10
11# Генератор занимает значительно меньше памяти
FAQ
В чем разница между return и yield?
return завершает функцию, yield приостанавливает выполнение и возвращает значение, сохраняя состояние функции для продолжения.
Когда использовать генераторы?
Используй генераторы при работе с большими данными, бесконечными последовательностями или когда нужно экономить память.