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 risultatii
di iter per i qualifunzione(i)
restituisce trueimap(funzione, iter)
passa uno a uno afunzione
i risultati diiter
e 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
.times
indica 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]