2009-06-07 17 views
9

Basta guardare i generatori Python, davvero impressionati da loro, ma ci sono cose da non usarli? Stavo pensando al codice C passato in cui leggere da un file, o le azioni dell'utente sarebbero aree. Ad esempio, è possibile utilizzare il generatore per richiedere all'utente l'immissione (immissione dei dati di base?) E il processo della funzione di chiamata che immette? ci sono problemi di prestazioni o di pulizia con cui preoccuparsi?Python Generator - cosa non usarlo per

risposta

12

Un problema con i generatori è che ottengono "consumati". Ciò significa che se è necessario ripetere nuovamente la sequenza, è necessario creare nuovamente il generatore.

Se la valutazione lazy è un problema, probabilmente non si desidera un'espressione di generatore. Ad esempio, se si desidera eseguire tutti i calcoli in anticipo (ad esempio, in modo che sia possibile rilasciare una risorsa), una comprensione di lista o ciclo è probabilmente la migliore.

Se si utilizza psyco, si otterrà un aumento significativo della velocità per le espressioni di elenco e per i loop, ma non per i generatori.

Anche piuttosto ovviamente, se è necessario ottenere la lunghezza della sequenza in anticipo, quindi non si vuole un generatore.

13

I generatori non persistono bene.

In genere, si verifica un errore durante il tentativo di mantenere un oggetto generatore.

>>> def generatorForEvenKeys(aDictionary): 
    for k in aDictionary: 
     if k % 2 == 0: yield aDictionary[k] 

>>> x = generatorForEvenKeys(someDictionary) 
>>> pickle.dump(x,file('temp.dat','wb')) 

si ottiene il seguente errore:

TypeError: can't pickle generator objects 
+0

+1 bene sapere – ebo

+0

Può fare un esempio? – bayer

+0

bayer: Esempio come segue: Sto iterando su un documento di testo e restituendo parole. Voglio mettere sottosopra il generatore in modo che possa continuare a leggere il documento di testo esattamente da dove avevo lasciato. Oops! Non posso. Che PITA. –

1

si utilizza un generatore quando si desidera avere qualcosa di essere iterateable, senza tenere l'intero elenco in memoria (questo è il motivo per cui xrange supporta sequenze molto più a lungo range in Python 2.x e inferiore)

Quando avete bisogno per caricare l'intera "lista di cose da produrre" in memoria, non c'è molto senso nell'usare un generatore - si può anche solo restituire una lista.

Per un esempio (un po 'forzato):

def my_pointless_generator(x): 
    thedata = range(x) # or thedata = list(range(x)) in Python 3.x 
    for x in thedata: 
     yield x 

..can essere riscritta proprio nel modo più efficiente ..

def my_pointless_generator(x): 
    return range(x)