2011-08-06 7 views
7

Estaba trabajando en un proyecto Flask, obteniendo algunos datos de un contenedor API. El contenedor devolvió un objeto generador, por lo que I print los valores (for obj in gen_object: print obj) antes de pasarlo a render_template() de Flask.¿Los objetos del generador Python se vuelven "inutilizables" después de atravesarlos?

Al solicitar la página mientras print ing los objetos, la página está vacía. Pero al eliminar el bucle for, la página representa el contenido del objeto generador.

@app.route('/') 
def front_page(): 
    top_stories = r.get_front_page(limit=10) 
    # this for loop prevents the template from rendering the stories 
    for s in top_stories: 
     print s 
    return render_template('template.html', stories=top_stories) 

Respuesta

9

Sí, los generadores deben consumirse una vez. Cada vez que iteramos un generador, le pedimos que nos dé otro valor, y si no hay más valores para dar, se lanza la excepción StopIteration que detendría la iteración. No hay forma de que el generador sepa que queremos repetirlo nuevamente sin clonarlo.

Mientras los registros pueden caber cómodamente en la memoria, me gustaría utilizar una lista en su lugar:

top_stories = list(top_stories) 

esa manera se puede repetir varias veces top_stories.

Hay una función llamada itertools.tee para copiar un iterador que también podría ayudarlo pero a veces es más lento que el simple uso de una lista. Referencia: http://docs.python.org/library/itertools.html?highlight=itertools.tee#itertools.tee

+0

También puede que no sea más eficiente en cuanto a la memoria que usar una lista, dependiendo de qué tan lejos se separan los usos separados de los iteradores teed. – hop

Cuestiones relacionadas