0Pricing
Python Academy · Урок

Функции-генераторы

Лениво создавайте значения с помощью yield

«Функции-генераторы» — бесплатный урок Python Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.

Что такое генератор

Функция-генератор выглядит как обычная функция, но использует yield вместо return или вместе с ним. Её вызов не выполняет тело функции, а возвращает объект-генератор, который является итератором.

def gen():
    yield 1
    yield 2
    yield 3

g = gen()
print(type(g).__name__)
print(list(g))

yield приостанавливает выполнение

При каждом вызове next() функция выполняется до первого yield, возвращает это значение и сохраняет своё состояние. Следующий вызов продолжает выполнение сразу после yield.

def steps():
    print('start')
    yield 'a'
    print('resumed')
    yield 'b'

g = steps()
print(next(g))
print(next(g))

Перебор генератора в цикле

Поскольку генератор является итератором, цикл for автоматически управляет им и останавливается, когда функция завершается, то есть внутри возникает StopIteration.

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for x in countdown(4):
    print(x)

Ленивое вычисление

Генераторы работают лениво: значения создаются только по запросу. Поэтому с их помощью можно моделировать очень большие или бесконечные последовательности, не расходуя много памяти.

def naturals():
    n = 1
    while True:
        yield n
        n += 1

g = naturals()
print(next(g), next(g), next(g))

Состояние между yield

Локальные переменные сохраняют свои значения между точками yield. Генератор сам запоминает место, на котором остановился, поэтому вручную вести индекс не нужно.

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

g = fib()
print([next(g) for _ in range(7)])

Генераторы и построение списка

Обычная функция создаёт и возвращает весь список сразу. Генератор выдаёт элементы по мере необходимости. Используйте генератор, когда последовательность велика или выполнение может завершиться досрочно.

def squares_list(n):
    result = []
    for i in range(n):
        result.append(i * i)
    return result

def squares_gen(n):
    for i in range(n):
        yield i * i

print(squares_list(5))
print(list(squares_gen(5)))

Досрочная остановка

Поскольку значения создаются лениво, можно выйти из цикла, и генератор просто не будет вычислять оставшуюся часть.

def naturals():
    n = 1
    while True:
        print('producing', n)
        yield n
        n += 1

for x in naturals():
    if x > 3:
        break
    print('got', x)

return внутри генератора

Обычный return в генераторе просто завершает его, вызывая StopIteration. Любое возвращённое Вами значение становится атрибутом value исключения, который большинство циклов игнорирует.

def up_to(stop):
    i = 0
    while True:
        if i >= stop:
            return
        yield i
        i += 1

print(list(up_to(4)))

Генераторы можно использовать только один раз

Как и любой итератор, генератор используется один раз. После исчерпания он больше ничего не выдаёт. Чтобы получить новый генератор, снова вызовите функцию.

def gen():
    yield 1
    yield 2

g = gen()
print(list(g))
print(list(g))
print(list(gen()))

Фильтрация с помощью генераторов

Генераторы позволяют создавать понятные конвейеры обработки данных. Здесь мы выдаём только чётные числа, по одному за раз.

def evens(numbers):
    for n in numbers:
        if n % 2 == 0:
            yield n

print(list(evens(range(10))))

Объединение генераторов

Один генератор может потреблять другой, образуя многоэтапный конвейер, в котором каждый этап работает лениво.

def numbers(n):
    for i in range(n):
        yield i

def doubled(src):
    for x in src:
        yield x * 2

print(list(doubled(numbers(5))))

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете функции-генераторы.

Итоги

Вы изучили функции-генераторы:

  • yield приостанавливает и возобновляет выполнение, сохраняя локальное состояние.
  • Вызов функции возвращает ленивый объект-генератор.
  • Генераторы экономят память и отлично подходят для конвейеров и бесконечных потоков.
  • Их можно использовать только один раз, как и любой итератор.

Далее Вы изучите ещё более компактные выражения-генераторы.

Часто задаваемые вопросы

Урок «Функции-генераторы» бесплатный?

Да — полный текст урока «Функции-генераторы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.

Чему я научусь в уроке «Функции-генераторы»?

Лениво создавайте значения с помощью yield Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Python Academy?

Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Функции-генераторы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Python Academy?

Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Протокол итератора
  2. Функции-генераторы
  3. Выражения-генераторы
  4. yield from и делегирование
← Назад к Python Academy