¿Cuáles son las ventajas de “artículo de rendimiento” en comparación con el iter de retorno (artículos)?

En los ejemplos a continuación, resp.results es un iterador.

Versión 1 :

items = [] for result in resp.results: item = process(result) items.append(item) return iter(items) 

Versión 2:

 for result in resp.results: yield process(result) 

¿El retorno de iter (elementos) en la Versión 1 es mejor / peor en términos de rendimiento / ahorro de memoria que simplemente devolver elementos?

En el “Libro de cocina de Python”, Alex dice que el iter explícito () es “más flexible pero que se usa con menos frecuencia”, pero ¿cuáles son los pros / contras de devolver iter (elementos) vs rendimiento como en la versión 2?

Además, ¿cuáles son las mejores maneras de probar un iterador y / o rendimiento? – ¿No puedes hacer len (resultados) para verificar el tamaño de la lista?

Es fácil volver a convertir un iterador o generador en una lista si lo necesita:

 results = [item for item in iterator] 

O como se señaló amablemente en los comentarios, un método aún más simple:

 results = list(iterator) 

El primero hace que todos los resultados se calculen y almacenen, mientras que el segundo es una carga lenta, por lo que los resultados se calculan solo cuando se solicitan. Es decir, uno almacenará y creará una lista de N elementos, mientras que el otro almacenará y creará 0 elementos hasta que comience a iterarlos.

Una mejor manera de pensar acerca de esto es usar ifilter (de itertools ) en el que estás haciendo lo mismo que el rendimiento, excepto que estás generando un iterador en lugar de un generador:

  ifilter(process, resp.results) 

Descubrí que los iteradores generalmente se ejecutan más rápido que los generadores en la serie 2.x, pero no puedo verificar ningún ahorro de costos en la serie 3.x.

Cuando está procesando una lista muy grande, entonces el yield item es mejor, ya que no consume mucha memoria.

Vea un excelente artículo en el generador http://www.dabeaz.com/generators/Generators.pdf

Puedes crear iteradores infinitos, pero no listas infinitas:

 def fibGen(): f0, f1 = 0, 1 while True: yield f0 f0, f1 = f1, f0+f1 

La ventaja y la desventaja del fragmento anterior es que todos los resultados se calculan por adelantado. Esto es útil si el tiempo entre la recuperación de cada elemento es crucial, pero no lo hará si el iterable es infinito o si el espacio es una preocupación.