2008-12-13 7 views

Respuesta

94

¿Entiende la lista de comprensiones? Si es así, una expresión de generador es como una lista de comprensión, pero en lugar de encontrar todos los elementos que le interesan y empaquetarlos en una lista, espera y arroja cada elemento fuera de la expresión, uno por 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 at 0xb7d5e02c> 
>>> 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. 
... 
>>> filtered_gen.next() 
5 
>>> filtered_gen.next() 
9 
>>> filtered_gen.next() 
6 
>>> filtered_gen.next() # 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 
>>> 

Debido a que una expresión generadora solamente tiene que ceder un elemento a la vez, puede conducir a grandes ahorros en el uso de la memoria. Las expresiones de generador tienen más sentido en los escenarios en los que necesita tomar un elemento a la vez, hacer muchos cálculos en función de ese elemento y luego pasar al siguiente elemento. Si necesita más de un valor, también puede usar una expresión de generador y tomar algunas a la vez. Si necesita todos los valores antes de que su programa continúe, utilice una lista de comprensión en su lugar.

12

Una comprensión de generador es la versión perezosa de una lista de comprensión.

Es como una lista de comprensión, excepto que devuelve un iterador en lugar de la lista, es decir, un objeto con un método next() que producirá el siguiente elemento.

Si no está familiarizado con la lista de comprensiones, vea here y para los generadores, consulte here.

4

La comprensión de lista/generador es una construcción que puede usar para crear una nueva lista/generador a partir de uno existente.

Digamos que desea generar la lista de los cuadrados de cada número del 1 al 10. Se puede hacer esto en Python:

>>> [x**2 for x in range(1,11)] 
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 

aquí, range(1,11) genera la lista [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], pero la función range no es un generador antes de Python 3.0, y por lo tanto el constructo que he usado es una lista de comprensión.

Si quería crear un generador que hace lo mismo, que podía hacerlo de esta manera:

>>> (x**2 for x in xrange(1,11)) 
<generator object at 0x7f0a79273488> 

En Python 3, sin embargo, range es un generador, por lo que el resultado depende sólo de la sintaxis usted usa (corchetes o corchetes redondos).

+1

esto es incorrecto. Si la expresión externa es un generador no tiene nada que ver con si la expresión interna es. Aunque obviamente, no hay mucho sentido en una expresión de generador que tome elementos de una lista, puedes hacerlo. – Antimony

+0

¿Se puede reescribir esto más claramente? Entiendo lo que dices, pero como dice Antimony, parece que estás diciendo algo más. (y lo que parece que está diciendo es incorrecto) –

2

La comprensión del generador es una forma fácil de crear generadores con una cierta estructura. Digamos que quiere un generator que emite uno por uno todos los números pares en your_list. Si se crea mediante el uso del estilo de la función sería la siguiente:

def allEvens(L): 
    for number in L: 
     if number % 2 is 0: 
      yield number 

evens = allEvens(yourList) 

que podría lograr el mismo resultado con esta expresión la comprensión del generador:

evens = (number for number in your_list if number % 2 == 0) 

En ambos casos, cuando se llama a next(evens) se obtener el siguiente número par en your_list.

0

La comprensión del generador es un enfoque para crear iterables, algo así como un cursor que se mueve sobre un recurso. Si conoce el cursor mysql o el cursor mongodb, puede tener en cuenta que la información real completa nunca se carga en la memoria de una vez, sino de a una por vez. El cursor se mueve hacia adelante y hacia atrás, pero siempre hay un elemento de fila/lista en la memoria.

En resumen, mediante el uso de generadores de comprensión puede crear fácilmente cursores en python.

0

Otro ejemplo de la comprensión del generador:

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 
Cuestiones relacionadas