Wiki Python para dados
Geradores e avaliação preguiçosa
Um gerador produz um item por vez, só quando pedido. É a mesma ideia do Spark preguiçoso, em pequena escala.
Uma função com yield não roda quando é chamada: ela devolve um gerador, e o corpo só anda quando alguém pede o próximo item. Isso deixa processar um arquivo maior que a memória, linha a linha.
def ler(linhas):
for linha in linhas:
print("lendo", linha)
yield linha.upper()
g = ler(["a", "b", "c"])
print("nada foi lido ainda")
print(next(g))
print(list(g))Saída (conferida)
nada foi lido ainda lendo a A lendo b lendo c ['B', 'C']
Gerador é de uma passada só
Depois de consumido, ele está vazio. Erro comum: calcular a soma e depois a contagem do mesmo gerador.
quadrados = (n * n for n in range(4))
print(sum(quadrados))
print(sum(quadrados))Saída (conferida)
14 0
Pipeline de geradores
Encadeados, os geradores formam um pipeline em que cada item atravessa todas as etapas antes do próximo entrar. Nenhuma lista intermediária é criada.
from itertools import islice
def numeros():
n = 0
while True:
n += 1
yield n
pares = (n for n in numeros() if n % 2 == 0)
dobrados = (n * 10 for n in pares)
print(list(islice(dobrados, 5)))Saída (conferida)
[20, 40, 60, 80, 100]
A fonte é infinita e mesmo assim o programa termina: só cinco itens foram pedidos. No Spark é parecido: transformação monta o plano, e só a ação (count, write, show) faz o trabalho acontecer.
- Para lotes de tamanho fixo,
itertools.batched(it, n)(Python 3.12+) devolve tuplas de aténitens.
Fontes
Conhecimento compartilhado pela Genesis Innovation.