itertools.pairwise() recorre un iterable y produce pares formados por elementos consecutivos. En lugar de administrar índices manualmente, recibes directamente (anterior, actual), lo que mejora la legibilidad y reduce errores en los límites de la secuencia.
La función fue incorporada en Python 3.10 y resulta útil en series temporales, validación de secuencias, detección de transiciones, geometría, registros, eventos y procesamiento de datos. Es lazy: genera cada par bajo demanda y no necesita copiar toda la entrada.
Cómo funciona pairwise
from itertools import pairwise
valores = [10, 14, 13, 20]
for anterior, actual in pairwise(valores):
print(anterior, actual)
El resultado contiene (10, 14), (14, 13) y (13, 20). Un iterable con menos de dos elementos no produce pares.
Calcular diferencias consecutivas
temperaturas = [21.2, 22.0, 21.7, 23.1]
diferencias = [b - a for a, b in pairwise(temperaturas)]
Este patrón aparece en métricas, precios, sensores y cualquier conjunto de datos ordenado en el tiempo. El código comunica la intención con claridad: comparar cada valor con el siguiente.
Detectar cambios de estado
estados = ["offline", "offline", "online", "online", "error"]
for anterior, actual in pairwise(estados):
if anterior != actual:
print(f"cambio: {anterior} -> {actual}")
En observabilidad, este enfoque permite localizar transiciones sin guardar manualmente una variable con el estado anterior.
Validar secuencias crecientes
def estrictamente_creciente(valores):
return all(a < b for a, b in pairwise(valores))
La combinación con all() mantiene la evaluación lazy y se detiene al encontrar la primera violación, lo que puede ahorrar trabajo en secuencias grandes.
Calcular intervalos entre fechas
from datetime import date
fechas = [date(2026, 1, 3), date(2026, 1, 8), date(2026, 1, 10)]
intervalos = [(b - a).days for a, b in pairwise(fechas)]
El mismo principio funciona con timestamps, versiones, posiciones geográficas, etapas de un proceso y puntos de control.
Construir segmentos
Cuando una lista representa puntos de una ruta, cada par consecutivo define un segmento.
puntos = [(0, 0), (3, 4), (6, 4)]
segmentos = list(pairwise(puntos))
La solución es más clara que range(len(puntos) - 1) y evita accesos repetidos por índice.
Pairwise frente a zip y slicing
pares = zip(valores, valores[1:])
Para listas pequeñas, zip con slicing funciona. Sin embargo, el slice crea otra lista y el patrón no se aplica directamente a generadores. Pairwise acepta cualquier iterable y conserva el comportamiento lazy.
Pairwise frente a tee
Antes de Python 3.10 era común implementar esta operación con itertools.tee(). Esa receta sigue siendo válida para compatibilidad, pero pairwise expresa mejor la intención.
from itertools import tee
def pairwise_compatible(iterable):
primero, segundo = tee(iterable)
next(segundo, None)
return zip(primero, segundo)
tee puede almacenar elementos temporalmente si sus iteradores avanzan a ritmos diferentes. Pairwise gestiona internamente el estado necesario para este caso concreto.
Uso con generadores
def lecturas():
for valor in range(1_000_000):
yield valor
for a, b in pairwise(lecturas()):
if b - a != 1:
break
No se crea una lista con un millón de elementos. Esta propiedad hace que pairwise sea adecuado para archivos, streams, cursores de bases de datos y pipelines extensos.
Detectar huecos
ids = [100, 101, 102, 106, 107]
for a, b in pairwise(ids):
if b != a + 1:
print("hueco entre", a, "y", b)
El patrón sirve para números de secuencia, lotes, offsets, facturas y registros de eventos.
Combinar pairwise con enumerate
for indice, (a, b) in enumerate(pairwise(valores), start=1):
print(indice, a, b)
Con inicio en uno, el índice corresponde a la posición del segundo elemento del par en la secuencia original. Conviene documentar esa convención.
Secuencias circulares
Pairwise no conecta automáticamente el último elemento con el primero. Para representar un ciclo, agrega o encadena explícitamente el primer elemento.
from itertools import chain
colores = ["rojo", "verde", "azul"]
pares_circulares = pairwise(chain(colores, colores[:1]))
Con un generador, conserva solo el primer elemento y encadénalo al final, considerando también el caso de un iterable vacío.
No modifiques la colección durante el recorrido
Cambiar una lista mientras pairwise la consume puede producir resultados inesperados. Es preferible generar una nueva secuencia o aplicar transformaciones antes de construir los pares.
Tratar datos ausentes
Las series reales suelen contener None, NaN o registros inválidos. Define si deseas filtrar, cortar el segmento o conservar el par para registrar el problema.
datos = [10, None, 12, 15]
validos = (x for x in datos if x is not None)
print(list(pairwise(validos)))
Filtrar cambia la vecindad: 10 y 12 pasan a ser consecutivos. Esa decisión puede ser correcta en un dominio y engañosa en otro.
Rendimiento
Pairwise tiene coste lineal y usa poca memoria adicional. Como no materializa todos los pares, suele ser eficiente. Aun así, la operación ejecutada para cada par puede dominar el tiempo total, especialmente si realiza entrada y salida.
Errores frecuentes
- Esperar salida de un iterable con un solo elemento.
- Suponer que el último elemento se conecta con el primero.
- Consumir un generador antes de entregarlo a pairwise.
- Ignorar valores ausentes que cambian la semántica de vecindad.
- Usar pairwise cuando se necesitan ventanas de tres o más elementos.
Ventanas mayores
Pairwise crea ventanas de exactamente dos elementos. Para ventanas deslizantes mayores, utiliza una receta con deque o iteradores alineados. itertools.batched produce bloques no superpuestos, una operación diferente.
Pruebas recomendadas
Prueba entrada vacía, un elemento, dos elementos, valores repetidos, datos inválidos y generadores grandes. Las pruebas basadas en propiedades son útiles para monotonicidad y detección de huecos.
Buenas prácticas
Confirma el orden de los datos, conserva la evaluación lazy cuando sea posible y usa nombres descriptivos como anterior y actual. Continúa con las guías de Academify sobre itertools en Python, generadores, list comprehensions y funciones en Python.
Conclusión
itertools.pairwise es una herramienta pequeña que resuelve un patrón frecuente de forma elegante. Elimina índices manuales, acepta cualquier iterable y combina bien con all, comprehensions y pipelines lazy. Cuando necesites comparar vecinos, detectar transiciones o calcular diferencias, pairwise debería estar entre tus primeras opciones.







