Cosa fa la comprensione del generatore? Come funziona? Non sono riuscito a trovare un tutorial su di esso.
Cosa fa la comprensione del generatore? Come funziona? Non sono riuscito a trovare un tutorial su di esso.
Risposte:
Capisci la comprensione delle liste? In tal caso, un'espressione generatore è come una comprensione di una lista, ma invece di trovare tutti gli elementi che ti interessano e comprimerli in una lista, attende e restituisce ogni elemento dall'espressione, uno per uno.
>>> my_list = [1, 3, 5, 9, 2, 6]
>>> filtered_list = [item for item in my_list if item > 3]
>>> print(filtered_list)
[5, 9, 6]
>>> len(filtered_list)
3
>>> # compare to generator expression
...
>>> filtered_gen = (item for item in my_list if item > 3)
>>> print(filtered_gen) # notice it's a generator object
<generator object <genexpr> at 0x7f2ad75f89e0>
>>> len(filtered_gen) # So technically, it has no length
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
>>> # We extract each item out individually. We'll do it manually first.
...
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # Should be all out of items and give an error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> # Yup, the generator is spent. No values for you!
...
>>> # Let's prove it gives the same results as our list comprehension
...
>>> filtered_gen = (item for item in my_list if item > 3)
>>> gen_to_list = list(filtered_gen)
>>> print(gen_to_list)
[5, 9, 6]
>>> filtered_list == gen_to_list
True
>>>
Poiché un'espressione del generatore deve produrre solo un elemento alla volta, può portare a grandi risparmi nell'utilizzo della memoria. Le espressioni del generatore hanno più senso negli scenari in cui è necessario prendere un elemento alla volta, eseguire molti calcoli basati su quell'elemento e quindi passare all'elemento successivo. Se hai bisogno di più di un valore, puoi anche usare un'espressione del generatore e prenderne alcuni alla volta. Se hai bisogno di tutti i valori prima che il tuo programma proceda, usa invece una comprensione dell'elenco.
next(...)invece che .__next__()in Python 3.
If you need more than one value, you can also use a generator expression and grab a few at a time. Potrebbe fornire un esempio su questo utilizzo? Grazie.
Una comprensione del generatore è la versione pigra di una comprensione dell'elenco.
È proprio come una comprensione di lista tranne per il fatto che restituisce un iteratore invece della lista, cioè un oggetto con un metodo next () che produrrà l'elemento successivo.
Se non hai familiarità con la comprensione delle liste, vedi qui e per i generatori vedi qui .
La comprensione della lista / generatore è un costrutto che puoi usare per creare una nuova lista / generatore da uno esistente.
Supponiamo che tu voglia generare l'elenco dei quadrati di ogni numero da 1 a 10. Puoi farlo in Python:
>>> [x**2 for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
qui, range(1,11)genera la lista [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ma la rangefunzione non è un generatore prima di Python 3.0, e quindi il costrutto che ho usato è una comprensione della lista.
Se volessi creare un generatore che faccia la stessa cosa, potrei farlo in questo modo:
>>> (x**2 for x in xrange(1,11))
<generator object at 0x7f0a79273488>
In Python 3, invece, rangeè un generatore, quindi il risultato dipende solo dalla sintassi che utilizzi (parentesi quadre o parentesi tonde).
La comprensione del generatore è un modo semplice per creare generatori con una certa struttura. Diciamo che vuoi un generatorche emetta uno per uno tutti i numeri pari in your_list. Se lo crei usando lo stile della funzione sarebbe come questo:
def allEvens( L ):
for number in L:
if number % 2 is 0:
yield number
evens = allEvens( yourList )
Potresti ottenere lo stesso risultato con questa espressione di comprensione del generatore:
evens = ( number for number in your_list if number % 2 == 0 )
In entrambi i casi, quando chiami next(evens)ricevi il successivo numero pari your_list.
La comprensione del generatore è un approccio per creare iterabili, qualcosa come un cursore che si muove su una risorsa. Se conosci il cursore mysql o il cursore mongodb, potresti essere consapevole del fatto che tutti i dati effettivi non vengono mai caricati nella memoria contemporaneamente, ma uno alla volta. Il cursore si sposta avanti e indietro, ma in memoria è sempre presente un elemento di una riga / elenco.
In breve, utilizzando la comprensione dei generatori puoi facilmente creare cursori in Python.
Un altro esempio di comprensione del generatore:
print 'Generator comprehensions'
def sq_num(n):
for num in (x**2 for x in range(n)):
yield num
for x in sq_num(10):
print x