Iteradores e o Protocolo de Iterador
A iteração está em toda parte em Python - loops for, compreensões, desempacotamento e sum. Objetos participam implementando o protocolo de iterador ou delegando para generators.
Receita
class Countdown:
def __init__(self, start: int) -> None:
self.current = start
def __iter__(self):
return self
def __next__(self) -> int:
if self.current < 0:
raise StopIteration
value = self.current
self.current -= 1
return value
for n in Countdown(3):
print(n)Quando usar isso:
- Travessia de sequência customizada sem armazenar uma lista completa
- Análise de dados em streaming, bloco por bloco
- Pipelines de transformação preguiçosos (lazy)
- Integração com
itertoolse loopsfor
Exemplo de Trabalho
from collections.abc import Iterable, Iterator
class CSVLines:
def __init__(self, lines: Iterable[str]) -> None:
self._lines = iter(lines)
def __iter__(self) -> Iterator[list[str]]:
for raw in self
O que isso demonstra:
- Iterable pode retornar um generator de
__iter__(generator é um iterator) iter()obtém um iterator;next()puxa itens atéStopIterationtakeconsome manualmente um iterator com leitura limitada- Separação entre iterável (reproduzível via novo iter) vs. iterator (passagem única)
Mergulho Profundo
Como Funciona
- Iterable - Implementa
__iter__retornando um iterator. - Iterator - Implementa
__iter__(retorna self) e__next__. - StopIteration - Sinaliza o fim; não deve ser capturado amplamente em torno de
for. - Funções generator -
yieldconstrói um iterator automaticamente. - iter(callable, sentinel) - Chama callable até o valor sentinel.
Resumo do Protocolo
| Objeto | Métodos Requeridos |
|---|---|
| Iterable | __iter__ |
| Iterator | __iter__, __next__ |
Notas Python
# iter com sentinel para blocos binários
with open("data.bin", "rb") as fh:
for chunk in iter(lambda: fh.read(4096), b""):
process(chunk)Armadilhas
- Iterable confundido com iterator - Iterator é esgotado após um
for. Correção: Chameiter()novamente apenas em iteráveis. - Levantar StopIteration em generator - Em generators use
returnpuro; em__next__levante StopIteration. - Iterable mutável durante a iteração - Erro de alteração de tamanho de dict/list. Correção: Tire um snapshot ou adie exclusões.
- getitem iteração legada - Antigo protocolo de sequência; prefira
__iter__. - Iterator infinito sem break - Trava o consumidor. Correção: Documente ou forneça
take/islice.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Função generator | Maioria das iterações customizadas | Necessita de estado de classe além do yield |
itertools | Álgebra padrão de iteradores | Loop simples único |
Materializar list | Necessita de reutilização/acesso aleatório | Streams muito grandes |
| Iterator assíncrono | async for com I/O | Pipeline apenas síncrono |
FAQs
Qual a diferença entre iterable e iterator?
Iterable produz iterators. Iterator produz itens uma vez até se esgotar.
Por que StopIteration?
Sinaliza o fim da iteração para a maquinaria do loop for - não é para controle de fluxo geral no código da aplicação.
Posso iterar duas vezes?
Somente se o objeto for iterável, retornando um novo iterator a cada chamada de iter(). Generators se esgotam após uma passagem.
O que o loop for faz?
it = iter(obj); while True: try: x = next(it) ... except StopIteration: break
Forma de 2 argumentos de iter()?
Chama repetidamente callable até sentinel - útil para leituras de stream.
collections.abc Iterable?
Verificação de instância estrutural - classes customizadas podem se registrar ou implementar __iter__.
generator vs classe iterator?
Generators são mais rápidos de escrever; classes quando estado complexo ou múltiplos métodos são necessários.
enumerate zip iteração?
Built-ins retornam iterators - consomem uma vez, eficientes em memória.
iteração async?
__aiter__/__anext__ com async for - veja a seção asyncio.
testando iterators?
list(iterator) materializa o esperado; afirma StopIteration em chamadas next extras.
Relacionados
- Generators & yield - iterators baseados em yield
- itertools - utilitários de iterator
- Comprehensions & Generator Expressions - sintaxe de genexp
- Abstract Base Classes - ABCs de Iterable
Versões da Pilha: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.