0Pricing
Python Academy · Урок

yield from и делегирование

Комбинируйте генераторы

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

Проблема, которую решает конструкция yield from

Когда один генератор должен выдать все значения другого итерируемого объекта, можно написать ручной цикл. yield from делает то же самое в одной строке.

def manual():
    for x in [1, 2, 3]:
        yield x

print(list(manual()))

Знакомство с yield from

yield from iterable делегирует работу этому итерируемому объекту и по очереди выдаёт все его значения. Это короче и понятнее, чем цикл пересылки значений.

def delegate():
    yield from [1, 2, 3]

print(list(delegate()))

Объединение нескольких источников

Можно последовательно использовать несколько конструкций yield from, чтобы лениво объединять последовательности.

def chained():
    yield from 'ab'
    yield from [1, 2]
    yield from range(2)

print(list(chained()))

Делегирование другому генератору

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

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

def report(n):
    print('evens:')
    yield from evens(n)

print(list(report(6)))

Выравнивание вложенных списков

Классический случай применения yield from — рекурсивное выравнивание: генератор делегирует работу самому себе для обработки вложенных списков.

def flatten(items):
    for item in items:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

print(list(flatten([1, [2, [3, 4]], 5])))

yield from и цикл

Обе приведённые ниже версии создают одинаковый результат. yield from предпочтительнее благодаря читаемости, а также потому, что передаёт дополнительные возможности, например отправку значений и результаты возврата.

def with_loop(src):
    for x in src:
        yield x

def with_yield_from(src):
    yield from src

print(list(with_loop(range(3))))
print(list(with_yield_from(range(3))))

Получение результата подгенератора

Если делегированный генератор возвращает значение с помощью return, выражение yield from принимает это значение. Так подгенераторы могут сообщать результат.

def counter(n):
    count = 0
    for i in range(n):
        yield i
        count += 1
    return count

def driver():
    total = yield from counter(3)
    print('subgen yielded', total, 'items')

list(driver())

Построение конвейера

Делегирование позволяет легко разделить конвейер на именованные этапы и объединить их.

def source():
    yield from range(5)

def only_odd(src):
    for x in src:
        if x % 2 == 1:
            yield x

def pipeline():
    yield from only_odd(source())

print(list(pipeline()))

Делегирование любому итерируемому объекту

yield from работает с любым итерируемым объектом, а не только с генераторами: со списками, кортежами, множествами, строками, ключами словарей и многими другими объектами.

def mixed():
    yield from {1, 2, 3}
    yield from ('a', 'b')

result = list(mixed())
print(sorted(str(x) for x in result))

Последовательное объединение генераторов

Можно создать генератор, который последовательно обходит несколько источников. Это удобно для объединения потоков данных.

def concat(*iterables):
    for it in iterables:
        yield from it

print(list(concat([1, 2], [3], [4, 5])))

Преимущество читаемости

Для глубоко вложенных или древовидных данных yield from позволяет сделать рекурсивные генераторы короткими и понятными по смыслу.

def walk(tree):
    yield tree['name']
    for child in tree.get('children', []):
        yield from walk(child)

tree = {'name': 'root', 'children': [
    {'name': 'a'},
    {'name': 'b', 'children': [{'name': 'c'}]}
]}
print(list(walk(tree)))

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

Проверьте, насколько хорошо Вы понимаете конструкцию yield from.

Итоги

Вы изучили yield from и делегирование:

  • Эта конструкция передаёт каждое значение внутреннего итерируемого объекта.
  • Она объединяет генераторы и позволяет выполнять рекурсивное выравнивание.
  • Она получает возвращаемое значение подгенератора.
  • Она понятнее ручного цикла пересылки значений.

Следующий курс: параллельное выполнение с использованием потоков и многопроцессности.

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

Урок «yield from и делегирование» бесплатный?

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

Чему я научусь в уроке «yield from и делегирование»?

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

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

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

Сколько времени занимает урок «yield from и делегирование»?

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

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

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

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

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