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 — локальная установка не требуется.
Все уроки этого курса
- Протокол итератора
- Функции-генераторы
- Выражения-генераторы
- yield from и делегирование