Geradores e yield
Iteradores lazy e economia de memória
Geradores são funções que usam yield para produzir valores um por vez, de forma lazy. Em vez de calcular todos os valores e retornar uma lista, um gerador produz um valor e pausa, retomando de onde parou na próxima chamada a next().
Geradores são ideais para processar grandes conjuntos de dados sem carregar tudo na memória. Eles implementam o protocolo de iteração automaticamente — podem ser usados diretamente em for loops.
Uma expressão geradora tem a mesma lógica de list comprehension mas usa parênteses () e é lazy. Geradores podem também receber valores via .send() e lidar com encerramento via .close().
# Gerador simples
def contar_ate(n):
i = 0
while i < n:
yield i
i += 1
for numero in contar_ate(5):
print(numero) # 0, 1, 2, 3, 4
# Gerador de Fibonacci infinito
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print([next(fib) for _ in range(8)])
# [0, 1, 1, 2, 3, 5, 8, 13]
# Processar arquivo linha por linha (sem carregar tudo)
def ler_linhas(caminho):
with open(caminho) as f:
for linha in f:
yield linha.strip()
# Generator expression
quadrados = (x**2 for x in range(1000)) # lazy!
soma = sum(quadrados) # calcula sob demanda
# Encadeando geradores (pipeline)
def filtrar_pares(nums):
return (n for n in nums if n % 2 == 0)
def quadrado(nums):
return (n**2 for n in nums)
resultado = quadrado(filtrar_pares(range(20)))Prefira geradores a listas quando o resultado será consumido uma única vez — economiza memória significativamente.