Обложка канала

Goal Gesture программирование, IT

Новости, статьи и полезные материалы из мира IT

Goal Gesture программирование, IT

4 года назад
Открыть в
Что такое генераторы в программировании? Они лениво раз за разом вычисляют новые значения, но не помнят, что было до этого. В программировании есть инструмент, который позволяет экономить память и при этом обрабатывать огромные массивы данных. Это генераторы. Мы рассмотрим работу генераторов на примере языка Python, но они есть и в других языках. Классический подход к обработке — итераторы Допустим, мы хотим вывести числа от 1 до 10 и для этого пишем такой код: for i in range(1,10): print(i) Это один из вариантов реализации цикла. Что делает компьютер, когда обрабатывает такое: Создаст в памяти область для хранения данных. Заполнит её числами от 1 до 10. На каждом шаге цикла компьютер возьмёт новые данные из этой области и выведет их на экран. При этом компьютер точно знает, какое значение у переменной i было на предыдущем шаге и будет на следующем, потому что все они хранятся в памяти. Но что, если нам понадобится несколько переменных с диапазоном значений? Например, так: a = range(1,100) b = range(1000,2000) for i in a: print(a[i-1] + b[i]) Когда мы запустим этот код, то увидим, что компьютер выделил большой кусок памяти для обеих переменных и что можно обратиться к отдельным ячейкам в таких диапазонах. Это удобно, когда нужно постоянно держать под рукой какие-то данные. Но если переменные со счётчиками не понадобятся, то память будет простаивать зря. 👉 Итератор в данном случае — это цикл, который обращается к диапазону значений и берёт по очереди оттуда данные. При этом все данные уже есть в памяти. Итераторы хороши своей предсказуемостью, но при обработке большого потока данных могут привести к расходу памяти и неоптимальной работе программы. Генераторы — вычисление данных «на лету» Генераторы работают иначе: вместо того чтобы сразу хранить в памяти все данные, они их генерируют на каждом шаге и отдают в работу. Вот как выглядит цикл с генератором: Цикл выполняется нужное количество раз. На каждом шаге цикла генератор получает какое-то значение, отдаёт его в нужное место и забывает всё напрочь. Генератор не помнит значение, которое он отдавал до этого, и не знает, что он будет отдавать на следующем шаге. Всё, что у него есть, — данные, которые нужно обработать на текущем шаге. Память под работу генератора выделяется, только когда он генерирует новые данные. Пока генератор стоит или не выдаёт данные — память не выделяется. Чаще всего генераторы используют как функции. Каждый раз, когда обращаются к такой функции-генератору, она делает так: Берёт новую порцию данных из указанного ей источника. Обрабатывает данные. Возвращает результат. Забывает про всё до следующего вызова. Обычно функции возвращают результат своей работы с помощью команды return (), а для генераторов есть специальная команда — yield (). Yield () работает так же, как и return (), только функция на ней не заканчивается, а ставится на паузу. При следующем вызове генератор возьмёт новую порцию данных, и единственное, что он помнит, — на каком месте он остановился в прошлый раз. Всё остальное генератор каждый раз считает заново.