Python versione Bignami - Generatori
Concetti di base
Un iteratore è un oggetto che ha un metodo next() che restituisce un valore o
lancia l'eccezione StopIteration.
Un generatore è una funzione che restituisce un iteratore.
Una funzione che contiene il comando yield viene automaticamente convertita
in una funzione che restituisce un iteratore.
Creazione
Da funzione:
def potenze(base):
val = base
while True:
yield val
val = val * base
def linee_numerate(file):
indice = 0
for linea in file:
yield indice, linea
indice = indice + i
# Stampa le potenze di 2
for i in potenze(2):
print i
# Mostra che il generatore 'potenze' restituisce un iteratore
iter = potenze(2)
while True:
try:
print iter.next()
except StopIteration:
break
In una classe:
class TreeNode:
def __iter__(self):
for node in self.children:
yield node
Definiti al volo:
a = (line[:-1] for line in file)
for line in a:
print line
a = (x.real, x.imag for x in complexNumbers)
for r, i in a:
print "Reale: %.2f, immag.: %.2f" % (r, i)
Da un altro oggetto:
lista = [1,2,3,4,5]
a = iter(lista)
Operazioni
for i in iter:itera gli elementi generatienumerate(iter)restituisce un generatore che genera coppie (indice, elemento di iter)
Alcune operazioni da from itertools import *:
chain(iter1, iter2...)restituisce un generatore che genera tutti i risultati di iter1, poi quelli di iter2, poi iter3 e cosí via.cycle(iter1)genera i risultati di iter1, salvandoli. Quando iter1 finisce, ne rigenera i risultati all'infinito.ifilter(funzione, iter)genera soli i risultatiidi iter per i qualifunzione(i)restituisce trueimap(funzione, iter)passa uno a uno afunzionei risultati diitere genera i risultatiislice(iter, [start,] stop [,step])restituisce gli elementi di iter a partire da quello in posizionestart(o dal primo), fino a quello in posizionestop(escluso), eventualmente prendendone uno ognistep.izip(iter1, iter2, ...)genera una tupla coi primi elementi di ogni iteratore, poi una tupla coi secondi, poi coi terzi e cosí viarepeat(val [, times])crea un generatore che genera sempreval.timesindica dopo quanto fermarsi, e se non è specificato non si ferma mai.x, y, z = tee(iter, 3)genera vari cloni diiter
Esempi:
# Aggiunge alla lista a tutte le righe del file, convertite in numeri interi
a.extend(imap(int,file))
# Stampa le righe di un file, una ogni tre
for i, riga in enumerate(file):
if i % 3 == 0:
print riga[:-1]
# Stampa le righe di file1 concatenate a quelle di file2
for riga1, riga2 in izip(file1, file2):
print riga1[:-1], riga2[:-1]