Ecco un esempio pertinente dai documenti del modulo 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)
Per Python 2, itertools.izipinvece di 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)
Come funziona:
Innanzitutto, vengono creati due iteratori paralleli ae b(la tee()chiamata), entrambi puntano al primo elemento dell'iterabile originale. Il secondo iteratore bviene spostato di un passo avanti (la next(b, None)) chiamata). A questo punto apunta a s0 e bpunta a s1. Entrambi ae bpossono attraversare l'iteratore originale in modo indipendente: la funzione izip prende i due iteratori e crea coppie di elementi restituiti, facendo avanzare entrambi gli iteratori allo stesso ritmo.
Un avvertimento: la tee()funzione produce due iteratori che possono avanzare indipendentemente l'uno dall'altro, ma ha un costo. Se uno degli iteratori avanza ulteriormente rispetto agli altri, è tee() necessario mantenere in memoria gli elementi consumati fino a quando il secondo iteratore non li assuma (non può "riavvolgere" l'iteratore originale). Qui non importa perché un iteratore è solo 1 passo avanti rispetto all'altro, ma in generale è facile usare molta memoria in questo modo.
E poiché tee()può assumere un nparametro, questo può essere utilizzato anche per più di due iteratori paralleli:
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)