Простой генератор
Условие
Напишите генератор, который yield-ит квадраты чисел от 1 до n.
Пример
for sq in squares(5): print(sq)
Вывод:
1
4
9
16
25
Дополнительно
Объясните разницу между генератором и итератором.
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Простой Генератор и Итераторы
Генератор — это функция, которая возвращает значения по одному, экономя память. Это мощный инструмент Python для работы с последовательностями.
Подход 1: Простой Генератор
Используем yield для возврата значений:
def squares(n: int):
for i in range(1, n + 1):
yield i * i
for sq in squares(5):
print(sq)
Вывод:
1
4
9
16
25
Подход 2: Генератор с Выражением
Компактная форма с generator expression:
def squares(n: int):
return (i * i for i in range(1, n + 1))
for sq in squares(5):
print(sq)
Это не совсем функция-генератор, а генераторное выражение, но работает одинаково.
Подход 3: Генератор с Дополнительной Логикой
Можно добавить фильтрацию или трансформацию:
def squares(n: int, start: int = 1, step: int = 1):
for i in range(start, n + 1, step):
yield i * i
for sq in squares(10, start=2, step=2):
print(sq)
Вывод:
4
16
36
64
100
Разница между Генератором и Итератором
Итератор — объект с методами __iter__() и __next__():
class SquaresIterator:
def __init__(self, n: int):
self.n = n
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.n:
self.current += 1
return self.current ** 2
else:
raise StopIteration
for sq in SquaresIterator(5):
print(sq)
Генератор — частный случай итератора, создаётся с помощью функции с yield:
def squares(n: int):
for i in range(1, n + 1):
yield i * i
for sq in squares(5):
print(sq)
Ключевые Отличия
| Аспект | Итератор | Генератор |
|---|---|---|
| Определение | Класс с __iter__ и __next__ | Функция с yield |
| Код | Больше кода, явная логика | Меньше кода, компактнее |
| Память | Зависит от реализации | Ленивое вычисление, минимум памяти |
| Состояние | Явно сохраняется в атрибутах | Сохраняется неявно в стеке вызовов |
| Простота | Сложнее для начинающих | Интуитивнее и читабельнее |
| Производительность | Немного быстрее | Немного медленнее, но разница минимальна |
Практические Примеры
# Генератор чисел Фибоначчи
def fibonacci(limit: int):
a, b = 0, 1
while a < limit:
yield a
a, b = b, a + b
for num in fibonacci(100):
print(num, end=' ')
# Генератор строк из файла
def read_lines(filename: str):
with open(filename) as f:
for line in f:
yield line.strip()
for line in read_lines('data.txt'):
print(line)
# Чтение большого файла без загрузки в память
def chunked_read(filename: str, chunk_size: int = 1024):
with open(filename, 'rb') as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
yield chunk
Преимущества Генераторов
1. Экономия памяти:
# Плохо: загружает всё в память
squares_list = [i * i for i in range(1000000)]
# Хорошо: ленивое вычисление
squares_gen = (i * i for i in range(1000000))
2. Бесконечные последовательности:
def infinite_counter():
n = 0
while True:
yield n
n += 1
for num in infinite_counter():
if num > 5:
break
print(num)
3. Конвейеры обработки данных:
def numbers():
for i in range(5):
yield i
def squared(numbers):
for n in numbers:
yield n * n
def filtered(numbers):
for n in numbers:
if n > 5:
yield n
result = filtered(squared(numbers()))
for num in result:
print(num)
Рекомендация
Используй генератор для этой задачи — это стандартный питонический способ:
- Компактный и читаемый код
- Минимум памяти
- Естественная семантика для последовательностей
- Показывает понимание концепций Python
Если попросят отличия от итератора, объясни: генератор — это удобный способ создать итератор без написания класса с методами __iter__ и __next__.