itertools.pairwise() percorre um iterável e produz pares formados por elementos consecutivos. Em vez de trabalhar com índices, você recebe diretamente (item_atual, item_seguinte), o que deixa o código mais legível e reduz erros de limite.
A função foi adicionada ao Python 3.10 e é especialmente útil em análise de séries temporais, validação de sequências, cálculo de diferenças, detecção de transições, geometria, logs e processamento de eventos. Ela é lazy: os pares são gerados sob demanda, sem copiar toda a coleção.
Como pairwise funciona
from itertools import pairwise
valores = [10, 14, 13, 20]
for anterior, atual in pairwise(valores):
print(anterior, atual)
O resultado contém os pares (10, 14), (14, 13) e (13, 20). Uma sequência com menos de dois itens não produz nenhum par.
Calcular diferenças consecutivas
from itertools import pairwise
temperaturas = [21.2, 22.0, 21.7, 23.1]
diferencas = [b - a for a, b in pairwise(temperaturas)]
print(diferencas)
Esse padrão aparece em métricas, preços, sensores e qualquer dado ordenado no tempo. O código expressa a intenção diretamente: comparar cada valor com o próximo.
Detectar mudanças de estado
estados = ["offline", "offline", "online", "online", "erro"]
for anterior, atual in pairwise(estados):
if anterior != atual:
print(f"mudança: {anterior} -> {atual}")
Em sistemas de observabilidade, esse formato ajuda a localizar transições sem armazenar manualmente uma variável anterior.
Validar sequências crescentes
def estritamente_crescente(valores):
return all(a < b for a, b in pairwise(valores))
O uso de all() mantém o processamento lazy e interrompe assim que encontra uma violação. Isso pode economizar trabalho em sequências grandes.
Encontrar intervalos em datas
from datetime import date
from itertools import pairwise
datas = [date(2026, 1, 3), date(2026, 1, 8), date(2026, 1, 10)]
intervalos = [(b - a).days for a, b in pairwise(datas)]
O mesmo raciocínio vale para timestamps, versões, posições geográficas e etapas de um processo.
Construir segmentos
Quando uma lista representa pontos de uma rota, cada par consecutivo define um segmento.
pontos = [(0, 0), (3, 4), (6, 4)]
segmentos = list(pairwise(pontos))
Isso evita o padrão mais verboso range(len(pontos) - 1) e elimina acessos repetidos por índice.
Comparação com zip e slicing
pares = zip(valores, valores[1:])
Para listas pequenas, zip com slicing funciona. Porém, o slice cria uma nova lista e não se aplica diretamente a geradores. pairwise aceita qualquer iterável e preserva o comportamento lazy.
Comparação com tee
Antes do Python 3.10, uma implementação comum usava itertools.tee(). Ela continua útil para compatibilidade, mas pairwise é mais clara e comunica melhor a intenção.
from itertools import tee
def pairwise_compativel(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
tee pode precisar armazenar itens temporariamente quando os iteradores avançam em ritmos diferentes. No uso de pairwise, esse detalhe já é tratado pela biblioteca.
Uso com geradores
def leituras():
for valor in range(1_000_000):
yield valor
for a, b in pairwise(leituras()):
if b - a != 1:
break
Nenhuma lista de um milhão de itens é criada. Essa característica torna a função adequada para arquivos, streams e pipelines de dados.
Detectar lacunas
ids = [100, 101, 102, 106, 107]
for a, b in pairwise(ids):
if b != a + 1:
print("lacuna entre", a, "e", b)
Esse padrão é útil para validar numeração, lotes, offsets e sequências de eventos.
Pairwise com enumerate
for indice, (a, b) in enumerate(pairwise(valores), start=1):
print(indice, a, b)
O índice representa a posição do segundo elemento no par quando o início é 1. Documente essa convenção para evitar confusão.
Sequências circulares
Pairwise não conecta automaticamente o último item ao primeiro. Para ciclos, acrescente explicitamente o primeiro elemento.
from itertools import chain
cores = ["vermelho", "verde", "azul"]
pares_circulares = pairwise(chain(cores, cores[:1]))
Em geradores, você pode guardar apenas o primeiro item e encadeá-lo ao final, tomando cuidado com iteráveis vazios.
Evite modificar a coleção durante o percurso
Alterar a lista enquanto pairwise a percorre pode produzir resultados inesperados. Prefira gerar uma nova coleção ou aplicar transformações antes de criar os pares.
Tratamento de dados ausentes
Em séries reais, valores None ou inválidos exigem uma política explícita. Você pode filtrar antes, interromper o segmento ou manter o par para registrar a ausência.
dados = [10, None, 12, 15]
validos = (x for x in dados if x is not None)
print(list(pairwise(validos)))
Filtrar altera a noção de vizinhança: 10 e 12 tornam-se consecutivos. Em alguns domínios isso é correto; em outros, o valor ausente precisa quebrar a série.
Desempenho
Pairwise tem custo linear em relação ao número de itens e memória adicional pequena. Como não materializa todos os pares, costuma ser uma escolha eficiente. Ainda assim, a função aplicada a cada par pode dominar o tempo total.
Erros comuns
- Esperar um par para uma sequência com um único elemento.
- Assumir que o último item será ligado ao primeiro.
- Consumir um gerador antes de passá-lo para pairwise.
- Ignorar valores ausentes que mudam a semântica da vizinhança.
- Usar pairwise quando o problema exige janelas de três ou mais elementos.
Janelas maiores
Pairwise cria apenas janelas de tamanho dois. Para janelas maiores, use uma combinação de iteradores, deque ou itertools.batched quando blocos não sobrepostos forem aceitáveis. Janelas deslizantes e lotes são conceitos diferentes.
Boas práticas
Garanta que os dados estejam na ordem correta, mantenha a transformação lazy sempre que possível e escolha nomes como anterior e atual. Para aprofundar, leia os guias da Academify sobre itertools no Python, generators, list comprehensions e funções em Python.
Conclusão
itertools.pairwise é uma ferramenta pequena que resolve um padrão recorrente com clareza. Ela elimina índices manuais, funciona com qualquer iterável e combina bem com all, comprehensions e pipelines lazy. Sempre que você precisar comparar vizinhos, detectar transições ou calcular deltas, pairwise deve estar entre as primeiras opções.







