Cómo recorrer un generador


81

¿Cómo se puede recorrer un generador? Pensé de esta manera:

gen = function_that_returns_a_generator(param1, param2)
if gen: # in case the generator is null
    while True:
        try:
            print gen.next()
        except StopIteration:
            break

¿Existe una forma más pitónica?


Sugeriría usar break; nocontinue
Jon Clements

De hecho, lo haría de esta manera en el caso de que el generador pueda lanzar una excepción en un elemento, pero no desea detener la iteración.
robbrit

Respuestas:


145

Simplemente

for x in gen:
    # whatever

hará el truco. Tenga en cuenta que if gensiempre vuelve True.


6
No, if genno siempre regresa True. Si la operación function_that_returns_a_generator()regresa None, se genevalúa Falseen la ifdeclaración.
drevicko

44
@drevicko: estaba asumiendo que function_that_returns_a_generator()devuelve un generador (suposición en negrita, ¿no es así?). Noneno es un generador.
Sven Marnach

Dado que OP solicita una "forma pitónica", esta respuesta parece bastante legítima, dado que Python aboga por EAFP ;-)
DerMike

17
for item in function_that_returns_a_generator(param1, param2):
    print item

No necesita preocuparse por la prueba para ver si su función devuelve algo, ya que si no hay nada devuelto, no ingresará al ciclo.


9

En caso de que no necesite la salida del generador porque solo le importan sus efectos secundarios, puede usar el siguiente resumen:

for _ in gen: pass

3
o simplementelist(gen)
aiven

7

Simplemente puede recorrerlo:

>>> gen = (i for i in range(1, 4))
>>> for i in gen: print i
1
2
3

Pero tenga en cuenta que solo puede realizar un bucle una vez. La próxima vez que el generador esté vacío:

>>> for i in gen: print i
>>> 

4

Simplemente trátelo como cualquier otro iterable:

for val in function_that_returns_a_generator(p1, p2):
    print val

Tenga en cuenta que if gen:siempre será Verdadero, por lo que es una prueba falsa


2

Si desea moverse manualmente a través del generador (es decir, trabajar con cada bucle manualmente), puede hacer algo como esto:

    from pdb import set_trace

    for x in gen:
        set_trace()
        #do whatever you want with x at the command prompt
        #use pdb commands to step through each loop of the generator e.g., >>c #continue   

1
desde pdb import set_trace # no () :)
Vlad K.

1

Las otras respuestas son buenas para escenarios complicados. Si simplemente desea transmitir los elementos a una lista:

x = list(generator)

(o, si solo desea activar el generador para hacer cosas, simplemente list(generator).

Para un preprocesamiento simple, use listas por comprensión:

x = [tup[0] for tup in generator]

O cuando desee ejecutar funciones simples:

# didn't assign to variable b/c we don't care about what the print() function returns
[print(x) for x in gen]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.