Aquí hay un ejemplo relevante de los documentos del módulo itertools :
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
Para Python 2, necesita en itertools.iziplugar de zip:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
Cómo funciona esto:
Primero, se crean dos iteradores paralelos ay b(la tee()llamada), ambos apuntando al primer elemento del iterable original. El segundo iterador, bse mueve 1 paso adelante (la next(b, None)) llamada). En este punto aapunta a s0 y bapunta a s1. Tanto ay bpuede atravesar el iterador original de forma independiente - la función IZIP toma los dos iteradores y hace que los pares de elementos devueltos, avanzando dos iteradores al mismo ritmo.
Una advertencia: la tee()función produce dos iteradores que pueden avanzar independientemente uno del otro, pero tiene un costo. Si uno de los iteradores avanza más que el otro, entonces tee() necesita mantener los elementos consumidos en la memoria hasta que el segundo iterador los consuma también (no puede 'rebobinar' el iterador original). Aquí no importa porque un iterador está solo un paso por delante del otro, pero en general es fácil usar mucha memoria de esta manera.
Y como tee()puede tomar un nparámetro, esto también se puede usar para más de dos iteradores paralelos:
def threes(iterator):
"s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)