Генератор в Python - это функция, которая использует ключевое слово yield для возврата значений по одному, по мере необходимости. 
В отличие от обычных функций, генераторы не хранят все результаты в памяти сразу, а генерируют их "на лету". Это позволяет эффективно работать с большими объемами данных или бесконечными последовательностями.
Создать генератор можно либо с помощью yield в функции, либо с помощью генераторного выражения (похожего на списковое включение, но с круглыми скобками ()).
Генератор в Python - это специальный тип итератора, который позволяет генерировать последовательность значений "лениво", то есть, по мере необходимости.  В отличие от обычных функций, которые возвращают сразу весь результат вычислений в виде списка или другой коллекции, генераторы возвращают объект-генератор, который можно итерировать с помощью цикла for или функции next().
Ключевые особенности генераторов:
yield:  Генераторы определяются с использованием ключевого слова yield вместо return.  Когда генератор встречает yield, он приостанавливает свое выполнение и возвращает значение, указанное после yield.  При следующем вызове next() генератор возобновляет выполнение с того места, где он остановился.Пример:
        
def my_generator(n):
    i = 0
    while i < n:
        yield i
        i += 1
# Создаем генератор
gen = my_generator(5)
# Итерируем по генератору
for value in gen:
    print(value) # Вывод: 0 1 2 3 4
# Или используем next()
gen = my_generator(3)
print(next(gen)) # Вывод: 0
print(next(gen)) # Вывод: 1
print(next(gen)) # Вывод: 2
try:
    print(next(gen)) # Вызывает StopIteration, так как все значения были сгенерированы
except StopIteration:
    print("Конец генератора")
        
    
    Альтернативный способ создания генераторов: генераторные выражения (Generator expressions):
Генераторные выражения – это компактный способ создания генераторов, похожий на списковые включения, но возвращающий объект-генератор вместо списка.
        
# Генераторное выражение для квадратов чисел от 0 до 4
squares = (x*x for x in range(5))
for square in squares:
    print(square) # Вывод: 0 1 4 9 16
        
    
    Когда использовать генераторы: