Capítulo 03: Estruturas Repetitivas (while, for), Iteradores, enumerate e zip
Especialização em Sistemas com Python & POO com Type Hints • Capítulo 03
🗺️ Mapa Conceitual do Tópico
flowchart TD
subgraph PROTOCOLO["Protocolo de Iteração do CPython"]
ITBL["Iterável (Iterable)\nImplementa __iter__() -> Iterator"]
ITOR["Iterador (Iterator)\nImplementa __next__() -> T | StopIteration"]
PVM["Instrução PVM FOR_ITER\nAvaliação em C com Alocação O(1) de Memória"]
end
subgraph ESTRUTURAS["Mecanismos de Fluxo Repetitivo"]
FOR["for ... in\nIteração sobre Sequências e Geradores"]
WHILE["while condicao:\nRepetição Sentinela com Walrus (:=)"]
ELSE_LOOP["Cláusula else do Laço\nExecuta se e somente se NÃO houver break"]
end
subgraph UTILITARIOS["Funções Built-in de Alta Performance"]
ENUM["enumerate(col, start=0)\nTuplas Indexadas sem Variáveis Globais"]
ZIP["zip(*cols, strict=True)\nSincronização Segura de Coleções Heterogêneas"]
RANGE["range(start, stop, step)\nSequência Aritmética Imutável e Preguiçosa"]
end
ITBL --> ITOR
ITOR --> PVM
PVM --> FOR
FOR --> UTILITARIOS
WHILE --> ELSE_LOOP
FOR --> ELSE_LOOP
style PROTOCOLO fill:#ede7f6,stroke:#512da8,stroke-width:2px
style ESTRUTURAS fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
style UTILITARIOS fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
🔁 1. O Protocolo Formal de Iteração do CPython
Em Python, a repetição é construída sobre um protocolo formal orientado a objetos composto por dois métodos dunder (Double Underscore):
- Iterável (
Iterable): Qualquer objeto capaz de retornar um iterador quando solicitado. Implementa o método__iter__()ou a sequência indexável__getitem__(). Exemplos:list,tuple,str,dict,set, geradores. - Iterador (
Iterator): O objeto de fluxo que mantém o estado da travessia. Implementa:__iter__(): Retorna a si mesmo (return self).__next__(): Retorna o próximo elemento da sequência ou lança a exceção controladaStopIterationquando o fluxo atinge o término.
# O que o CPython faz internamente em todo 'for item in colecao:':
iterador = iter(colecao) # colecao.__iter__()
while True:
try:
item = next(iterador) # iterador.__next__()
# Corpo do laço
except StopIteration:
break # Fim natural da iteração
A instrução de bytecode FOR_ITER da PVM captura a exceção StopIteration diretamente na camada de C, garantindo que laços for em Python sejam ordens de magnitude mais rápidos e seguros que contadores manuais incrementados por software.
⚙️ 2. Estrutura while e o Operador Walrus (:= / PEP 572)
A estrutura while executa seu bloco repetidamente enquanto uma expressão booleana permanecer verdadeira. É a escolha primária quando o número de iterações é desconhecido a priori (ex.: leitura de fluxos de rede, sockets, buffers ou polling de filas).
Leitura com Sentinela e Atribuição em Expressão
O operador Walrus (:=), introduzido na PEP 572, permite atribuir valores a variáveis dentro da própria condição do laço, eliminando redundâncias de código e leituras duplicadas:
from pathlib import Path
def ler_arquivo_em_blocos(caminho: Path, tamanho_buffer: int = 4096) -> int:
total_bytes: int = 0
with caminho.open("rb") as arquivo:
# Atribuição e verificação no mesmo passo sem duplicar arquivo.read():
while bloco := arquivo.read(tamanho_buffer):
total_bytes += len(bloco)
return total_bytes
🧰 3. As Ferramentas Built-in de Iteração
O Python oferece utilitários em nível de compilador C para tornar a iteração limpa e legível:
| Função Built-in | Parâmetros Chave | Finalidade em Engenharia | Exemplo Idiomático |
|---|---|---|---|
range() |
start, stop[, step] |
Gera intervalos aritméticos sem alocar a lista completa na RAM ($O(1)$ de memória). | for i in range(0, 100, 5): |
enumerate() |
iterable[, start=0] |
Produz tuplas (indice, elemento), eliminando variáveis contadoras manuais. |
for idx, user in enumerate(usuarios, start=1): |
zip() |
*iterables, strict=True |
Agrupa $N$ coleções em tuplas sincronizadas $i$-ésimas. | for k, v in zip(chaves, valores, strict=True): |
reversed() |
sequence |
Itera no sentido inverso sem duplicar ou mutar a coleção original. | for item in reversed(pilha): |
A Segurança de zip(..., strict=True) (Python 3.10+)
Tradicionalmente, a função zip() encerrava silenciosamente a iteração quando o iterável mais curto acabava, descartando elementos excedentes sem aviso. A partir do Python 3.10, o parâmetro strict=True lança ValueError se os iteráveis possuírem comprimentos divergentes, prevenindo perda catastrófica de dados em auditorias:
codigos: list[str] = ["A1", "B2", "C3"]
precos: list[Decimal] = [Decimal("10.00"), Decimal("25.00")]
# Lança ValueError("zip() argument 2 is shorter than argument 1")
for cod, preco in zip(codigos, precos, strict=True):
processar(cod, preco)
🔀 4. A Cláusula else em Laços Repetitivos
Uma das construções mais elegantes e incompreendidas do Python é a cláusula else associada a laços for e while. O bloco else somente é executado se o laço for concluído até o fim, isto é, sem ter sido interrompido por um break:
def buscar_transacao_suspeita(transacoes: list[dict[str, Any]], limite_risco: Decimal) -> None:
for tx in transacoes:
if tx["score_risco"] >= limite_risco:
print(f"Alerta: Fraude detectada na transação {tx['id']}!")
break
else:
# Executado APENAS se nenhuma transação atingiu o limite de risco
print("Auditoria concluída: Lote 100% em conformidade operacional.")
Essa construção substitui flags booleanas de controle (como fraude_encontrada = False) e melhora a legibilidade do código.
⚡ 5. Análise de Desempenho e Boas Práticas
| Padrão de Repetição | Complexidade Espacial | Eficiência de Cache | Recomendação de Uso |
|---|---|---|---|
for tradicional com append() |
$O(N)$ em memória | Média (múltiplas realocações dinâmicas de vetor) | Quando o corpo possui regras de negócio complexas com chamadas I/O. |
| List Comprehension | $O(N)$ em memória | Alta (Otimizado em bytecode C) | Transformações lineares simples e filtros declarativos rápidos. |
Expressões Geradoras (yield) |
$O(1)$ constante | Máxima (Avaliação Lazy sob demanda) | Processamento de milhões de registros, streams e arquivos volumosos. |
Funções Nativas (sum, any, all) |
$O(1)$ constante | Imediata (Execução em C sem overhead) | Reduções agregadas diretas sobre iteráveis. |