Las siguientes son pautas aproximadas y conjeturas educadas basadas en la experiencia. Debería timeito perfilar su caso de uso concreto para obtener números concretos, y esos números pueden estar ocasionalmente en desacuerdo con los siguientes.
La comprensión de una lista suele ser un poco más rápida que el forbucle precisamente equivalente (que en realidad construye una lista), muy probablemente porque no tiene que buscar la lista y su appendmétodo en cada iteración. Sin embargo, una comprensión de la lista todavía hace un bucle de nivel de código de bytes:
>>> dis.dis(<the code object for `[x for x in range(10)]`>)
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 12 (to 21)
9 STORE_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 LIST_APPEND 2
18 JUMP_ABSOLUTE 6
>> 21 RETURN_VALUE
Usar una comprensión de la lista en lugar de un bucle que no construye una lista, acumular sin sentido una lista de valores sin sentido y luego tirar la lista, a menudo es más lento debido a la sobrecarga de crear y extender la lista. Las comprensiones de listas no son mágicas, es inherentemente más rápido que un buen bucle antiguo.
En cuanto a las funciones de procesamiento de listas funcionales: si bien están escritas en C y probablemente superan a las funciones equivalentes escritas en Python, son no necesariamente la opción más rápida. Se espera algo de velocidad si la función también está escrita en C. Pero la mayoría de los casos que usan una lambda(u otra función de Python), la sobrecarga de configurar repetidamente los marcos de pila de Python, etc., consume cualquier ahorro. Simplemente hacer el mismo trabajo en línea, sin llamadas a funciones (por ejemplo, una comprensión de la lista en lugar de mapo filter) es a menudo un poco más rápido.
Supongamos que en un juego que estoy desarrollando necesito dibujar mapas complejos y enormes usando bucles. Esta pregunta sería definitivamente relevante, ya que si una comprensión de la lista, por ejemplo, es realmente más rápida, sería una opción mucho mejor para evitar retrasos (a pesar de la complejidad visual del código).
Lo más probable es que si un código como este no es lo suficientemente rápido cuando se escribe en un buen Python no "optimizado", ninguna cantidad de micro optimización de nivel de Python lo hará lo suficientemente rápido y debe comenzar a pensar en caer a C. Las micro optimizaciones a menudo pueden acelerar el código de Python considerablemente, hay un límite bajo (en términos absolutos) para esto. Además, incluso antes de alcanzar ese techo, se vuelve simplemente más rentable (15% de aceleración frente a 300% de aceleración con el mismo esfuerzo) para morder la bala y escribir algo de C.
Usted pregunta específicamente sobre
map(),filter()yreduce(), pero supongo que quiere saber sobre programación funcional en general. Habiendo probado esto yo mismo en el problema de calcular distancias entre todos los puntos dentro de un conjunto de puntos, la programación funcional (usando lastarmapfunción delitertoolsmódulo incorporado ) resultó ser un poco más lenta que los bucles for (tomando 1.25 veces más, en hecho). Aquí está el código de muestra que utilicé:¿La versión funcional es más rápida que la versión de procedimiento?
fuente
Escribí un script simple que prueba la velocidad y esto es lo que descubrí. En realidad, el bucle fue más rápido en mi caso. Eso realmente me sorprendió, mira abajo (estaba calculando la suma de cuadrados).
fuente
intdesquare_sum4también hace que sea un poco más rápido y un poco más lento que el bucle.Yo modifiqué @ código de Alisa y se utiliza
cProfilepara mostrar por qué lista por comprensión es más rápido:Aquí están los resultados:
EN MI HUMILDE OPINIÓN:
reduceymapen general son bastante lentos. No solo eso, usandosumen los iteradores quemapregresó es lento, en comparación consumcon una listafor_looputiliza append, que por supuesto es lento hasta cierto puntosummucho más rápida, en contraste conmapfuente
Agregando un giro a la respuesta de Alphii , en realidad el bucle for sería el segundo mejor y aproximadamente 6 veces más lento que
mapLos principales cambios han sido eliminar las
sumllamadas lentas , así como las probablemente innecesariasint()en el último caso. Poner el bucle y el mapa for en los mismos términos lo convierte en un hecho bastante real. Recuerde que las lambdas son conceptos funcionales y, en teoría, no deberían tener efectos secundarios, pero, bueno, pueden tener efectos secundarios como sumara. Resultados en este caso con Python 3.6.1, Ubuntu 14.04, Intel (R) Core (TM) i7-4770 CPU @ 3.40GHzfuente
Logré modificar algunos de los códigos de @ alpiii y descubrí que la comprensión de la Lista es un poco más rápida que para el bucle. Puede ser causado por
int(), no es justo entre la comprensión de la lista y el bucle for.fuente