Módulo 7 - Geradores e iteradores avançados
Generator expressions e a memória
9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Escrever uma generator expression trocando colchetes por parênteses.
- Entender a diferença de memória entre lista e gerador.
- Saber que um gerador só pode ser percorrido uma vez.
- Reconhecer quando usar cada um.
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: Generator expressions e a memória.
Os objetivos desta aula. Escrever uma generator expression trocando colchetes por parênteses. Entender a diferença de memória entre lista e gerador. Saber que um gerador só pode ser percorrido uma vez. Reconhecer quando usar cada um.
Veja o essencial, parte por parte.
Só trocar colchetes por parênteses. List comprehension usa colchetes e cria a lista inteira na memória.
A economia de memória em números. Suponha que você queira somar os quadrados de dez milhões de números.
O gerador se esgota: consumo único. Vai percorrer os valores mais de uma vez? Então lista.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Só trocar colchetes por parênteses
Você já conhece a list comprehension do Intermediário, aquela expressão entre colchetes que constrói uma lista. A generator expression é irmã dela, com uma única diferença de escrita: troca os colchetes por parênteses. O efeito, porém, muda tudo. A list comprehension calcula todos os valores de uma vez e os guarda em uma lista completa na memória. A generator expression não calcula nada de imediato; ela devolve um gerador que produzirá cada valor só quando pedido.
quadrados_lista = [n * n for n in range(5)] # colchetes: lista pronta
print(quadrados_lista) # [0, 1, 4, 9, 16]
quadrados_ger = (n * n for n in range(5)) # parenteses: gerador
print(quadrados_ger) # <generator object ...>
print(list(quadrados_ger)) # [0, 1, 4, 9, 16] quando consumidoMesma lógica; colchetes criam a lista, parênteses criam um gerador preguiçoso.
No exemplo, a list comprehension já é a lista com os cinco quadrados. A generator expression é um objeto gerador que ainda não calculou nada; ele produz os valores conforme você os consome, seja com list, seja em um for. Para cinco números a diferença é irrelevante. A questão aparece quando os dados são grandes, e é aí que a economia de memória do gerador faz diferença de verdade.
A economia de memória em números
Suponha que você queira somar os quadrados de dez milhões de números. Com a list comprehension, o Python cria uma lista com dez milhões de itens na memória só para depois somá-los, o que consome centenas de megabytes à toa. Com a generator expression, nenhum item é guardado: cada quadrado é produzido, somado e descartado, um de cada vez. O uso de memória fica praticamente constante, independentemente do tamanho da entrada. É a diferença entre caber e estourar a memória.
# Pesado: cria uma lista de 10 milhoes de itens so para somar
total = sum([n * n for n in range(10_000_000)])
# Leve: nao guarda nada; soma um quadrado por vez
total = sum(n * n for n in range(10_000_000))
# Quando a generator expression e o unico argumento,
# os parenteses extras nem sao necessarios.Com sum, o gerador soma sem materializar a lista inteira: memória quase constante.
| Aspecto | List comprehension | Generator expression |
|---|---|---|
| Sintaxe | Colchetes [ ] | Parênteses ( ) |
| Quando calcula | Tudo de uma vez | Um item por vez, sob demanda |
| Uso de memória | Proporcional ao tamanho | Praticamente constante |
| Pode reusar? | Sim, é uma lista | Não, esgota após um percurso |
Lista contra gerador: mesma lógica, comportamentos de memória opostos.
O gerador se esgota: consumo único
Há um preço na economia, e ignorá-lo causa bugs sutis. Um gerador pode ser percorrido uma só vez. Depois de consumido, ele fica vazio: um segundo for sobre o mesmo gerador não produz nada, sem erro nenhum, o que confunde. A lista, por guardar tudo, pode ser percorrida quantas vezes você quiser. Então a decisão é clara: se você precisa dos valores mais de uma vez, use uma lista; se vai percorrer só uma vez, especialmente com dados grandes, prefira o gerador.
ger = (n for n in range(3))
print(list(ger)) # [0, 1, 2] primeiro percurso consome tudo
print(list(ger)) # [] o gerador ja esta esgotado
# Uma lista pode ser percorrida varias vezes:
lst = [n for n in range(3)]
print(list(lst)) # [0, 1, 2]
print(list(lst)) # [0, 1, 2] continua disponivelPercorrer o gerador uma segunda vez devolve vazio; a lista permanece reutilizável.
Teste rápido
Qual é a diferença central entre (n*n for n in dados) e [n*n for n in dados]?
Perguntas frequentes
- Quando os parênteses da generator expression são opcionais?
- Quando a generator expression é o único argumento de uma função, como em sum(n*n for n in dados). Nesse caso, os parênteses da chamada já servem, e você não precisa de um par extra. Se houver outros argumentos, ou se quiser guardar o gerador em uma variável, aí os parênteses próprios são necessários.
- Gerador é sempre melhor que lista?
- Não. O gerador ganha em memória quando você percorre uma vez só e os dados são grandes. Mas se você precisa dos valores mais de uma vez, ou de índice, len e fatiamento, a lista é a escolha certa, porque o gerador não oferece nada disso e se esgota após um percurso. Cada um tem seu momento.
- Por que o segundo for sobre um gerador não devolve nada?
- Porque o gerador guarda uma posição que só avança e, uma vez percorrido até o fim, fica esgotado. Não há erro; ele simplesmente não produz mais valores. É uma pegadinha comum: se você precisa percorrer duas vezes, materialize em uma lista com list(gerador) ou recrie o gerador.
- Dá para filtrar dentro de uma generator expression?
- Dá, com um if no fim, igual à list comprehension: (n for n in dados if n > 0). O filtro também é preguiçoso, aplicado item a item conforme você consome. Isso permite encadear filtros e transformações sem materializar nenhuma etapa intermediária, tema da próxima aula sobre pipelines.
- O gerador é mais rápido que a lista?
- Depende do uso. Ele evita o custo de construir a lista inteira, o que ajuda quando você não precisa de todos os valores ao mesmo tempo. Mas a velocidade de produzir cada item é parecida. O ganho principal do gerador é memória, não uma corrida de velocidade; muitas vezes os dois têm desempenho de tempo semelhante.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.