Módulo 13 - Geradores e iteradores
Função geradora com yield
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Escrever uma função geradora usando yield.
- Entender que yield pausa a função em vez de encerrá-la.
- Comparar o comportamento de yield com o de return.
- Perceber que chamar a função devolve um gerador, não o resultado pronto.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Função geradora com yield.
Os objetivos desta aula. Escrever uma função geradora usando yield. Entender que yield pausa a função em vez de encerrá-la. Comparar o comportamento de yield com o de return. Perceber que chamar a função devolve um gerador, não o resultado pronto.
Veja o essencial, parte por parte.
yield: devolver sem terminar. Uma função vira geradora quando você usa yield no corpo dela.
yield e return lado a lado. O contraste com return deixa tudo mais nítido.
Conferindo o entendimento. Esperar que chamar a função geradora já imprima ou calcule tudo. Não: ela só devolve o gerador.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
yield: devolver sem terminar
Na aula anterior você viu que o for precisa de um iterador que responda a next() e levante StopIteration no fim. Escrever isso na mão dá trabalho. O yield é o atalho oficial do Python para criar iteradores sem esse esforço. Basta usar yield dentro de uma função e ela deixa de ser comum: vira uma função geradora. A diferença de mentalidade é grande. Uma função normal calcula tudo e devolve um resultado pronto com return. Uma função geradora produz itens aos poucos, um a cada yield, pausando entre eles.
Pense no yield como um botão de pausa que também entrega algo pela janela. Quando a execução chega a um yield, três coisas acontecem: o valor à direita do yield é entregue a quem está percorrendo, a função congela naquela linha exata, com todas as suas variáveis intactas, e o controle volta para quem pediu o item. No próximo next(), a função descongela e segue da linha seguinte ao yield, como se o tempo não tivesse passado. Esse congelamento e descongelamento é o que dá aos geradores o seu superpoder.
def contagem_regressiva(n):
while n > 0:
yield n # entrega n e pausa aqui
n = n - 1 # continua daqui no proximo pedido
print("Fim!")
for numero in contagem_regressiva(3):
print(numero)
# 3
# 2
# 1
# Fim!A cada volta do while, yield entrega um número e pausa; o for pede o próximo.
yield e return lado a lado
O contraste com return deixa tudo mais nítido. Uma função com return roda até encontrar o return, devolve aquele valor e acaba: qualquer código depois do return não roda naquela chamada. Uma função com yield pode entregar muitos valores, um por vez, e continua viva entre as entregas. Um return dentro de uma função geradora não devolve valor para o for; ele apenas encerra a geração, equivalendo a um StopIteration. É a diferença entre entregar um pacote fechado e abrir uma torneira que pinga sob demanda.
def com_return():
return [1, 2, 3] # calcula tudo e devolve a lista pronta
def com_yield():
yield 1 # entrega 1 e pausa
yield 2 # entrega 2 e pausa
yield 3 # entrega 3 e pausa
print(com_return()) # [1, 2, 3]
print(com_yield()) # <generator object com_yield at 0x...>
print(list(com_yield())) # [1, 2, 3]com_return devolve a lista na hora; com_yield devolve um gerador que produz sob demanda.
Repare no detalhe do exemplo: chamar com_yield() não imprime 1, 2 e 3. Ele devolve um objeto gerador, ainda parado, que só produz os valores quando alguém os pede. Foi por isso que envolvemos com list(), que percorre o gerador do início ao fim e junta tudo numa lista. No dia a dia você raramente faz isso, porque o mais comum é percorrer o gerador direto com um for, aproveitando exatamente que ele produz aos poucos. Guardar essa vantagem, produzir sob demanda em vez de tudo de uma vez, é o que a próxima aula explora a fundo.
return
- Encerra a função na hora
- Devolve um único resultado pronto
- Código depois dele não roda
- Calcula tudo antes de entregar
yield
- Pausa a função e a mantém viva
- Entrega vários valores, um por vez
- A função continua da linha seguinte
- Produz item a item, sob demanda
Conferindo o entendimento
O ponto para levar desta aula é que yield muda o contrato da função. Ela para de ser algo que roda e devolve um resultado, e passa a ser uma fábrica que entrega itens quando pedidos, pausando entre eles. Chamar a função só constrói a fábrica, o gerador; nada roda até você começar a puxar os itens com um for ou com next(). Esse detalhe confunde no começo e vale fixar bem, porque é a base de todo o resto do módulo, incluindo as generator expressions e os pipelines de geradores encadeados.
Teste rápido
O que acontece quando a execução de uma função geradora chega a um yield?
Perguntas frequentes
- Uma função pode ter yield e return juntos?
- Pode. Se há pelo menos um yield, a função é geradora. Um return dentro dela não devolve valor para o for: ele só encerra a geração, funcionando como um fim antecipado, equivalente a StopIteration. Você usa return sem valor quando quer parar de produzir itens antes do fim natural.
- Por que chamar a função geradora não roda o código dela?
- Porque o objetivo é produzir sob demanda. Chamar a função constrói e devolve o objeto gerador, ainda parado no começo. O corpo só avança quando você pede itens, com um for ou com next(). É esse adiamento que permite trabalhar com sequências grandes sem calcular tudo de uma vez.
- Posso ter vários yield na mesma função?
- Sim, e é comum. Cada yield que a execução alcança entrega um item e pausa. Eles podem estar em sequência, dentro de laços ou dentro de condições. A função vai entregando valores na ordem em que os yield são executados, retomando de onde parou a cada pedido.
- Como transformo o resultado de um gerador em lista?
- Basta envolver o gerador com list(), como em list(minha_funcao()). Isso percorre o gerador do início ao fim e junta todos os itens numa lista. Faça isso apenas quando precisar mesmo de todos os itens na memória; muitas vezes percorrer com for é melhor.
- yield deixa o código mais lento?
- Não, ao contrário em muitos casos. Como o gerador produz item por item, ele evita construir listas gigantes na memória e permite começar a usar os primeiros resultados antes de calcular os últimos. Para sequências grandes, costuma ser mais rápido a sentir e muito mais leve na memória.
- Qual a diferença prática para uma função que devolve uma lista?
- A função com return monta a lista inteira antes de devolver, ocupando memória proporcional ao tamanho. A geradora entrega um item de cada vez, sem guardar todos. Se você só vai percorrer os itens uma vez, o gerador faz o mesmo trabalho gastando muito menos memória.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.