[Python] izip "à la tee"

Pietro Battiston me a pietrobattiston.it
Mer 5 Feb 2014 12:13:44 CET


Ciao a tutti,

ho a che fare con un codice analogo a questo:

NUMVAL = 5

def coppie():
    for i in range(NUMVAL):
        yield 1, 2

zip(*coppie())


Com'è giusto che sia, ottengo [(1, 1, 1, 1, 1), (2, 2, 2, 2, 2)].
E se preferisco continuare a giocare con gli iteratori, assumendo che io
debba ad esempio effettuare una qualche operazione su ogni elemento del
risultato, posso sostituire l'ultima riga con:

from itertools import izip

a, b = izip(*coppie()):

for i in range(3):
    quello_che_mi_pare_con(a[i])

for i in range(3):
    qualcos_altro_con(a[i])


Problema: supponiamo che invece NUMVAL sia 10 000 000. Il codice sopra
funziona, ma occupa un sacco di memoria, perché a e b sono tuple, non
iteratori (o se preferite, ancora prima, perché il "*" nella chiamata a
izip non è lazy). Peggio ancora se al posto di "for i in range(NUMVAL)"
ho "while True": non ci sarebbe in principio nulla di male a consumare
un tot di elementi dai due generatori infiniti... ma non posso farlo
come sopra.

In altre parole, se pensiamo a zip() come alla trasposizione di una
matrice, izip() permette di assumere che una dimensione della matrice
sia infinita... ma io ho bisogno di assumere che sia infinita l'altra!

Dopo un po' di ragionamento sono venuto fuori con questa mostruosità:

from itertools import tee, chain, imap
from operator import itemgetter

def iizip(iter_in):
    first = iter_in.next()
    return [imap(itemgetter(i), chain([first], iterable))
            for i, iterable in enumerate(tee(iter_in, len(first)))]

... da usare senza "*":

a, b = iizip(coppie())

... ma mi domandavo, e vi domando, se esiste qualcosa di più semplice
che mi è sfuggito.


(mi domandavo anche se fosse possibile assumere che la matrice sia
infinita _in entrambe le direzioni_, ma mi sono risposto che non avrebbe
molto senso, dato che un tee con returnvalue iterabile dovrebbe tenere
in memoria tutti i valori già visti da uno qualsiasi dei generatori...
però se qualcosa esiste ne sarei comunque curioso)

Grazie di qualsiasi dritta,

Pietro



Maggiori informazioni sulla lista Python