Módulo 7 - Geradores e iteradores avançados

Delegação com yield from

9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Substituir um for com yield por um yield from equivalente.
  • Usar yield from para achatar geradores aninhados.
  • Compor geradores reaproveitando outros geradores.
  • Entender por que yield from é base para corrotinas.

De um for com yield para yield from

Um padrão aparece o tempo todo: dentro de um gerador, você quer produzir todos os valores de outro gerador. A forma manual é um laço que repassa cada item: for x in outro: yield x. Funciona, mas é repetitivo e esconde a intenção. O yield from expressa a mesma ideia em uma linha e deixa claro que você está delegando a produção ao gerador interno. É açúcar sintático, com um bônus: no caso das corrotinas, ele também repassa valores enviados de volta, o que o laço manual não faz.

def contar(inicio, fim):
    for n in range(inicio, fim):
        yield n

# Forma manual: repassa item a item
def juntar_manual():
    for x in contar(0, 3):
        yield x
    for x in contar(10, 13):
        yield x

# Forma com yield from: delega a producao
def juntar():
    yield from contar(0, 3)
    yield from contar(10, 13)

print(list(juntar()))  # [0, 1, 2, 10, 11, 12]

yield from substitui o laço que repassa itens, deixando a delegação explícita.

As duas versões de juntar produzem exatamente a mesma sequência, mas a com yield from se lê melhor: cada linha diz produza tudo daquele gerador. Quando um gerador delega para vários outros em sequência, o yield from encadeia essas fontes de forma limpa. É o começo de uma ideia poderosa: compor geradores como se fossem peças de encaixe.

Achatar estruturas e compor geradores

Um uso muito prático do yield from é achatar estruturas aninhadas. Imagine uma lista de listas que você quer percorrer como se fosse uma sequência única. Com yield from, um gerador percorre cada sublista e delega a produção dos itens dela, resultando em um fluxo plano. E como o próprio gerador pode chamar a si mesmo, o yield from combina naturalmente com recursão para achatar estruturas de profundidade qualquer.

def achatar(estrutura):
    for elemento in estrutura:
        if isinstance(elemento, list):
            yield from achatar(elemento)   # delega recursivamente
        else:
            yield elemento

aninhada = [1, [2, 3, [4, 5]], 6, [7]]
print(list(achatar(aninhada)))  # [1, 2, 3, 4, 5, 6, 7]

yield from com recursão achata uma lista aninhada de profundidade arbitrária.

Uma ponte para o que vem depois

Além da conveniência, o yield from tem um papel histórico importante. Antes da sintaxe moderna de async e await, a programação assíncrona em Python era construída sobre geradores e yield from: um gerador delegava a outro e, quando o interno precisava esperar por algo, esse controle subia pela cadeia de delegação até o laço que coordenava tudo. A palavra await de hoje ocupa, em muitos aspectos, o lugar que o yield from ocupava então. Você verá o async moderno no módulo dedicado; aqui fica a semente.

Não é preciso decorar essa relação histórica agora. O que importa é perceber que geradores não são um canto isolado da linguagem: eles são a fundação sobre a qual a iteração, os pipelines de dados e até a concorrência assíncrona foram construídos. Dominar yield e yield from é, ao mesmo tempo, resolver problemas do dia a dia com elegância e preparar o terreno para os temas mais avançados que ainda vêm pela frente no curso.

Teste rápido

O que a linha yield from outro_gerador faz dentro de um gerador?

Perguntas frequentes

yield from é só um atalho para o laço com yield?
Para geradores simples que só produzem valores, sim, é um atalho mais legível. Mas ele faz um pouco mais: no caso de corrotinas, o yield from também estabelece um canal de mão dupla, repassando ao gerador interno os valores enviados com send e propagando o valor de retorno. Por isso ele é mais do que açúcar quando se entra no território das corrotinas.
Posso usar yield from com uma lista comum, não só com geradores?
Pode. O yield from funciona com qualquer iterável: listas, tuplas, strings, outros geradores. Ele produz os itens do iterável um a um. Escrever yield from [1, 2, 3] cede 1, depois 2, depois 3. Isso o torna útil para intercalar valores fixos e geradores dentro da mesma função geradora.
yield from ajuda a achatar qualquer estrutura aninhada?
Ajuda muito quando combinado com recursão: o gerador testa cada elemento e, se for uma coleção, delega a si mesmo com yield from; se for um valor simples, cede o valor. Assim ele achata estruturas de qualquer profundidade. Só é preciso decidir quais tipos contam como aninhados, para não tentar percorrer, por exemplo, uma string caractere a caractere sem querer.
Qual a vantagem de compor geradores com yield from?
Reaproveitamento e clareza. Você escreve geradores pequenos, cada um com uma responsabilidade, e os combina em geradores maiores sem reescrever laços. O código fica modular: um gerador filtra, outro transforma, um terceiro os une com yield from. E tudo permanece preguiçoso, sem materializar etapas intermediárias na memória.
Preciso entender corrotinas para usar yield from no dia a dia?
Não. Para os usos comuns, encadear e achatar geradores, basta pensar nele como produza tudo daquele iterável. A ligação com corrotinas e a história do async é um bônus de contexto, útil quando você chegar ao módulo de programação assíncrona. No cotidiano, o yield from já se paga só pela legibilidade.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.