python coding-style foreach list-comprehension

En Python, ¿es mejor usar listas de comprensión o para cada bucle?



title in python plot (7)

¿Cuál de los siguientes es mejor usar y por qué?

Método 1:

for k, v in os.environ.items(): print "%s=%s" % (k, v)

Método 2:

print "/n".join(["%s=%s" % (k, v) for k,v in os.environ.items()])

Tiendo a dirigirme hacia el primero como más comprensible, pero eso podría ser porque soy nuevo en Python y las comprensiones de la lista todavía me resultan algo ajenas. ¿La segunda forma se considera más pitonica? Supongo que no hay diferencia en el rendimiento, pero puedo estar equivocado. ¿Cuáles serían las ventajas y desventajas de estas 2 técnicas?

(Código tomado de Inmersión en Python )


El primero en mi opinión, porque:

  • No construye una gran cadena.
  • No crea una lista enorme (se puede arreglar fácilmente con un generador, eliminando el [] ).

En ambos casos, accede a los elementos de la misma manera (utilizando el iterador de diccionario).


Encuentro mejor el primer ejemplo, menos detallado, más claro y más legible.

En mi opinión, ve con lo que mejor logra tu intención, después de todo:

Los programas deben escribirse para que las personas los lean, y solo de manera incidental para que las máquinas los ejecuten.

- de "Estructura e interpretación de programas informáticos" por Abelson y Sussman

Por cierto, dado que recién estás empezando a aprender Python, comienza a aprender la nueva sintaxis de Formato de cadena de inmediato:

for k, v in os.environ.items(): print "{0}={1}".format(k, v)


Estoy de acuerdo con @Ben, @Tim, @Steven:

  • la legibilidad es lo más importante (haz "importar esto" para recordar lo que es)
  • un listcomp puede o no ser mucho más rápido que una versión de ciclo iterativo ... depende del número total de llamadas a funciones que se realizan
  • Si decides ir con listcomps con grandes conjuntos de datos, es mejor usar expresiones generadoras

Ejemplo:

print "/n".join("%s=%s" % (k, v) for k,v in os.environ.iteritems())

en el fragmento de código anterior, realicé dos cambios ... Reemplacé el listcomp por un genexp y cambié la llamada a iteritems() . [esta tendencia avanza, ya que en Python 3, iteritems() reemplaza y se renombra a items() .]


La comprensión de la lista es más del doble de rápido que el bucle explícito. Basa en la variación de Ben James, pero reemplace el x ** 2 con una función más trivial x + 2, las dos alternativas son:

def foo(n): L = [] for x in xrange(n): L.append(x+2) return L def bar(n): return [x+2 for x in xrange(n)]

Resultado del tiempo:

In [674]: timeit foo(1000) 10000 loops, best of 3: 195 us per loop In [675]: timeit bar(1000) 10000 loops, best of 3: 81.7 us per loop

La comprensión de la lista gana por un amplio margen.

Acepto que la legibilidad debe ser una prioridad sobre la optimización del rendimiento. Sin embargo, la legibilidad está en el ojo del espectador. ¡Cuando aprendo por primera vez Python, la comprensión de la lista es una cosa extraña que me resulta difícil de comprender! : -O Pero una vez que me acostumbré, se convierte en una notación de mano corta muy buena. Si quieres llegar a dominar Python, debes dominar la comprensión de la lista.


Los ejemplos de código particulares que ha elegido no demuestran ninguna ventaja de la comprensión de la lista, porque se está (mal) utilizando para la tarea trivial de imprimir. En este caso simple elegiría el bucle simple for .

En muchos otros casos, querrá proporcionar una lista real a otra función o método, y la comprensión de la lista es la forma más fácil y legible de hacerlo.

Un ejemplo que mostraría claramente la superioridad de la comp de la lista podría hacerse sustituyendo el ejemplo de print por uno que implique la creación de otra lista real, añadiéndole uno en cada iteración del ciclo for :

L = [] for x in range(10): L.append(x**2)

Da la misma L como:

L = [x**2 for x in range(10)]


Si la iteración se realiza por su efecto secundario (como en el ejemplo de "impresión"), entonces un ciclo es más claro.

Si la iteración se ejecuta para construir un valor compuesto, entonces las listas de comprensión son generalmente más legibles.


se supone que las listas de comprensión se ejecutan en el nivel C, de modo que si hay un bucle enorme, las listas de comprensión son una buena opción.