Ответ
Генератор в Python — это специальный итератор, который позволяет лениво (по требованию) генерировать значения, не храня всю последовательность в памяти одновременно. Это делает их исключительно эффективными для работы с большими или бесконечными потоками данных.
Два основных способа создания:
-
Функция-генератор (Generator function): Использует ключевое слово
yieldвместоreturn. При вызове такая функция возвращает объект-генератор, а её выполнение приостанавливается после каждогоyieldи возобновляется при следующем вызовеnext().def countdown(n): """Генератор, который отсчитывает от n до 1.""" while n > 0: yield n # Возвращает значение и приостанавливается n -= 1 # По достижении конца функция неявно вызывает StopIteration # Использование for number in countdown(5): print(number) # 5, 4, 3, 2, 1 # Или вручную gen = countdown(3) print(next(gen)) # 3 print(next(gen)) # 2 print(next(gen)) # 1 # print(next(gen)) # Вызовет StopIteration -
Генераторное выражение (Generator expression): Похоже на list comprehension, но использует круглые скобки и ленивые вычисления.
# List comprehension (сразу создаёт список в памяти) squares_list = [x**2 for x in range(1000000)] # Занимает много памяти # Generator expression (генерирует значения на лету) squares_gen = (x**2 for x in range(1000000)) # Практически не занимает памяти print(next(squares_gen)) # 0 print(next(squares_gen)) # 1
Ключевые преимущества:
- Экономия памяти: значения вычисляются и возвращаются по одному.
- Ленивые вычисления: генератор не начинает работу, пока не запрошено первое значение.
- Работа с бесконечными последовательностями:
def infinite_counter(): i = 0 while True: yield i i += 1
Под капотом: Генераторы реализуют протокол итератора (методы __iter__() и __next__()), а также имеют методы .send(value), .throw(exception) и .close() для более сложного взаимодействия.
Ответ 18+ 🔞
А, генераторы в Python! Ну это, блядь, одна из тех штук, которая сначала кажется какой-то мартышлюшкой, а потом понимаешь — ёперный театр, как же без них жил-то.
Представь себе, чувак, обычная функция — это как буфет. Зашёл, набрал полную тарелку всего (то есть весь список в памяти), сел жрать. А генератор — это суши-конвейер. Сидишь, и тебе по одной штучке подвозят, когда попросишь. Не надо сразу овердохуища данных в оперативку тащить.
Как их делают, этих хитрожопых:
-
Функция-генератор. Всё просто: пишешь функцию, но вместо
returnставишьyield. И всё — она уже не функция, а генератор, сам от себя охуевший от такой метаморфозы.def countdown(n): """Генератор, который отсчитывает от n до 1.""" while n > 0: yield n # Выплюнул значение и уснул до следующего раза n -= 1 # Дошёл до конца — тихо сдох (StopIteration) # Использование for number in countdown(5): print(number) # 5, 4, 3, 2, 1 # Или вручную, как мудак gen = countdown(3) print(next(gen)) # 3 print(next(gen)) # 2 print(next(gen)) # 1 # print(next(gen)) # А тут тебе в глаз — StopIterationСуть в том, что после
yieldфункция замирает, запоминает, где остановилась, и ждёт следующего пинкаnext(). Красота, я тебя в сраку. -
Генераторное выражение. Это вообще чих-пых тебя в сраку, какая элегантная хуйня. Как list comprehension, но в круглых скобках и без жадности.
# List comprehension — жадный уёбок, сразу всё в память грузит squares_list = [x**2 for x in range(1000000)] # Память кончилась, комп встал # Generator expression — хитрая жопа, отдаёт по одному squares_gen = (x**2 for x in range(1000000)) # Памяти жрёт как кот наплакал print(next(squares_gen)) # 0 print(next(squares_gen)) # 1
А главные плюсы-то какие, ёпта?
- Память не жрёт. Серьёзно, можно хоть терабайтный файл читать строчку за строчкой, и ничего не взорвётся.
- Ленивый как Фарлаф. Не начнёт работать, пока не скажешь «дай».
-
Бесконечные штуки делать можно. Вот смотри, ни хуя себе простой пример:
def infinite_counter(): i = 0 while True: yield i i += 1Попробуй такой список в память запихнуть — будет вам хиросима и нигерсраки. А генератору да похуй, он тебе хоть до скончания века числа выдавать будет.
Под капотом там, конечно, магия: методы __iter__, __next__, ещё можно в него значения .send() кидать или исключения .throw(). Но для начала просто запомни: yield — твой друг, когда данных дохуя, а память одна. Всё гениальное просто, как хуй с горы.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶