POTHIEDU Não Decore a Resposta. Entenda o Caminho

O Que São Geradores

O Que São Geradores

Geradores: o que são e por que todo mundo fala deles sem explicar direito

Geradores são funções especiais que retornam valores um por um, sem carregar tudo na memória de uma vez. A diferença prática é simples: em vez de construir uma lista inteira e retornar, você vai produzindo itens sob demanda com a palavra-chave yield. No Python, quando você vê algo como isso:

def minha_sequencia(n):
    for i in range(n):
        yield i * 2

Você está olhando para um gerador. A função não executa imediatamente. Ela só começa a rodar quando você pede um valor, como num loop ou usando next(). O que acontece no dia a dia é que você processa dados sem precisar armazená-los inteiros na RAM. Ler um arquivo de 50GB linha por linha, processar feeds de API, gerar combinações enormes... tudo isso vira trivial com geradores. Eu passei semanas tentando entender isso porque os tutoriais sempre mostram o exemplo chato dos números de Fibonacci. A parte que ninguém explica é o fluxo de controle. Quando um gerador dá yield, ele pousa. O estado da função inteira — variáveis locais, posição do loop, tudo — fica salvo. Na próxima chamada, ele retoma exatamente de onde parou.

Tem um detalhe que complica as coisas: geradores não são iteráveis duas vezes. Se você fizer um for loop completo e quiser percorrer de novo, precisa criar outro gerador. Isso me pegou uma vez num projeto de ETL onde eu precisava aplicar dois filtros sequenciais na mesma sequência de dados vindo de um gerador. Eu estava achando que era bug até perceber que o primeiro loop tinha consumido tudo. A solução foi simples: transformar o gerador em uma lista só nos pontos onde eu precisava reutilizar, ou encadear os filtros num único gerador. Ficar armazenando listas grandes desfaz o propósito, então o ideal é encadear tudo numa única corrente de geração quando possível.

O que são Geradores Reais? - Vamos Estudar Física
O que são Geradores Reais? - Vamos Estudar Física

Como usar geradores de verdade

O uso mais comum é em loops. Você não chama next() manualmente na maioria das vezes. O Python faz isso automaticamente: Aqui o gerador lê uma linha por vez do arquivo. Se o arquivo tiver milhões de linhas, a memória não explode. Cada iteração do loop consome uma linha, processa, e a próxima chamada busca a próxima linha. É assim que bibliotecas como pandas funcionam por baixo quando você usa chunksize. Generators also support sending values into them with send() e recebendo valores com yield como expressão:

def acumulador():
    total = 0
    while True:
        valor = yield total
        if valor is not None:
            total += valor

Isso é menos comum no dia a dia mas útil em pipelines de processamento onde você quer injetar dados externos durante a execução. O primeiro erro é achar que geradores aceleram código. Eles economizam memória, não tempo de CPU. Às vezes até deixam mais lento por causa da sobrecarga de criar frames de execução separados. O segundo erro é tratar geradores como se fossem listas. Não tem len(), não tem indexação, não tem slice. Se você precisa desses recursos, use uma lista mesmo ou transforme com list() no momento certo.

Um problema específico que encontrei: geradores aninhados. Quando você passa um gerador para outra função que também é um gerador, qualquer exceção que ocorra no interior pode ser difícil de rastrear. O traceback mostra a linha no yield externo, não onde o erro realmente aconteceu. Minha solução foi envolver os geradores internos em blocos try/except que re-lançam com informação adicional.

O que são Grupos Geradores? - R7 Geradores - Especialistas em ...
O que são Grupos Geradores? - R7 Geradores - Especialistas em ...

Quando NÃO usar geradores

Se você precisa acessar dados aleatoriamente, fazer múltiplas passagens, ou precisa saber o tamanho antes de processar, geradores vão te dar dor de cabeça. Nesses casos, listas, tuplas ou outras estruturas são mais adequadas. Também tem o caso dos geradores infinitos. Eles são úteis mas perigosos se você não controlar o consumo. Chamar list() num gerador infinito trava o programa. Sempre verifique se há um limite antes de materializar. A versão atual do Python traz algumas melhorias nos geradores, como a possibilidade de usar yield from para delegar a sub-iteradores de forma mais limpa, mas o comportamento fundamental continua o mesmo desde a versão 2.2. Se você está começando agora, gastar tempo entendendo geradores vale muito a pena. Eles aparecem em praticamente qualquer código Python não trivial e dominar isso muda como você pensa sobre processamento de dados.