2012-06-09 17 views
5

So che mi manca qualcosa di semplice, ma non lo vedo.Generatore Espressione vs rendimento: perché non funziona 'next()'?

Se ho un generatore di espressione come questa:

>>> serializer=(sn for sn in xrange(0,sys.maxint)) 

io in grado di generare, con facilità, interi singoli come questo:

>>> serializer.next() 
0 
>>> serializer.next() 
1 
>>> serializer.next() 
2 

Se scrivo un generatore come questo:

>>> def ser(): 
... for sn in xrange(0,100000): 
...  yield sn 

Non è disponibile:

>>> ser().next() 
0 
>>> ser().next() 
0 
>>> ser().next() 
0 

??? Cosa mi manca ???

risposta

19

ser() crea il generatore. Quindi, ogni volta che chiami ser(), ti viene inviata una nuova istanza di generatore. È necessario utilizzare proprio come l'espressione:

serializer = ser() 
serializer.next() 

Si consideri che, se non ha lavoro in questo modo, si potrebbe sempre e solo utilizzare la funzione ser() una sola volta e non avrebbe mai potuto ripristinarlo. Inoltre, puoi modificare la funzione di servizio per accettare un numero intero massimo e rendere il tuo programma più flessibile.

def ser(n=sys.maxint): 
    for sn in xrange(0, n): 
     yield sn 
+1

Thx! Sapevo che doveva essere semplice ... – dawg

+2

nessun problema. è sicuramente non ovvio, dal momento che l'altro tipo di funzioni principali che fanno questo (decoratori) hanno un esplicito 'return wrapper' in loro, che immagino sia implicito/magicamente creato dall'istruzione' yield': P –

4
ser() 

inizializza un generatore nuova ogni volta.

risolvere il problema fare qualcosa di simile:

s = ser() 
next(s) # next is preferred over .next which is why .next has been removed in Py3 
next(s) 
5

Nel secondo esempio si continua a creare una nuova istanza, a partire da un nuovo generatore.

g = ser() 
g.next() 
g.next() 

Creare il generatore di una volta e riutilizzarlo.

Problemi correlati