Ce qui suit sont des directives approximatives et des suppositions éclairées basées sur l'expérience. Vous devriez timeit
ou profiler votre cas d'utilisation concret pour obtenir des chiffres précis, et ces chiffres peuvent parfois être en désaccord avec ce qui suit.
Une compréhension de liste est généralement un tout petit peu plus rapide que la for
boucle exactement équivalente (qui construit en fait une liste), probablement parce qu'elle n'a pas à rechercher la liste et sa append
méthode à chaque itération. Cependant, une compréhension de liste effectue toujours une boucle au niveau du bytecode:
>>> 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
Utiliser une compréhension de liste à la place d'une boucle qui ne construit pas de liste, accumuler de manière absurde une liste de valeurs sans signification et ensuite jeter la liste, est souvent plus lent raison de la surcharge de création et d'extension de la liste. Les compréhensions de listes ne sont pas de la magie qui est intrinsèquement plus rapide qu'une bonne vieille boucle.
Quant aux fonctions de traitement de listes fonctionnelles: bien qu'elles soient écrites en C et surpassent probablement les fonctions équivalentes écrites en Python, elles ne sont pas nécessairement l'option la plus rapide. Une certaine accélération est attendue si la fonction est également écrite en C. Mais dans la plupart des cas utilisant une lambda
(ou une autre fonction Python), la surcharge de la configuration répétée des cadres de pile Python, etc. consomme des économies. Faire simplement le même travail en ligne, sans appel de fonction (par exemple, une compréhension de liste au lieu de map
ou filter
) est souvent légèrement plus rapide.
Supposons que dans un jeu que je développe, j'ai besoin de dessiner des cartes complexes et énormes en utilisant des boucles for. Cette question serait certainement pertinente, car si une liste-compréhension, par exemple, est effectivement plus rapide, ce serait une bien meilleure option afin d'éviter les décalages (malgré la complexité visuelle du code).
Il y a de fortes chances que si un code comme celui-ci n'est pas déjà assez rapide lorsqu'il est écrit en bon Python non "optimisé", aucune micro-optimisation de niveau Python ne le rendra assez rapide et vous devriez commencer à penser à passer en C. Les micro-optimisations peuvent souvent accélérer considérablement le code Python, il y a une faible limite (en termes absolus) à cela. De plus, même avant d'atteindre ce plafond, il devient tout simplement plus rentable (15% d'accélération contre 300% d'accélération avec le même effort) de mordre la balle et d'écrire du C.
Vous demandez spécifiquement sur
map()
,filter()
etreduce()
, mais je suppose que vous voulez savoir sur la programmation fonctionnelle en général. Ayant moi-même testé cela sur le problème du calcul des distances entre tous les points dans un ensemble de points, la programmation fonctionnelle (utilisant lastarmap
fonction duitertools
module intégré) s'est avérée légèrement plus lente que les boucles for (prenant 1,25 fois plus longtemps, en fait). Voici l'exemple de code que j'ai utilisé:La version fonctionnelle est-elle plus rapide que la version procédurale?
la source
J'ai écrit un script simple qui teste la vitesse et c'est ce que j'ai découvert. En fait, la boucle for était la plus rapide dans mon cas. Cela m'a vraiment surpris, regardez ci-dessous (calculait la somme des carrés).
la source
int
in lesquare_sum4
rend également un peu plus rapide et juste un peu plus lent que la boucle for.J'ai modifié le code de @ Alisa et utilisé
cProfile
pour montrer pourquoi la compréhension de liste est plus rapide:Voici les résultats:
A MON HUMBLE AVIS:
reduce
etmap
sont en général assez lents. Non seulement cela, l'utilisationsum
sur les itérateurs qui sontmap
retournés est lente, par rapport àsum
une listefor_loop
utilise append, qui est bien sûr lent dans une certaine mesuresum
beaucoup plus rapide, contrairement àmap
la source
En ajoutant une torsion à la réponse Alphii , en fait la boucle for serait la deuxième meilleure et environ 6 fois plus lente que
map
Les principaux changements ont été d'éliminer les
sum
appels lents , ainsi que les appels probablement inutilesint()
dans le dernier cas. Mettre la boucle for et la carte dans les mêmes termes en fait tout à fait un fait. Rappelez-vous que les lambdas sont des concepts fonctionnels et ne devraient théoriquement pas avoir d'effets secondaires, mais, eh bien, ils peuvent avoir des effets secondaires comme l'ajout dea
. Résultats dans ce cas avec Python 3.6.1, Ubuntu 14.04, processeur Intel (R) Core (TM) i7-4770 à 3,40 GHzla source
J'ai réussi à modifier une partie du code de @ alpiii et j'ai découvert que la compréhension de liste est un peu plus rapide que la boucle for. Cela peut être causé par
int()
, ce n'est pas juste entre la compréhension de la liste et la boucle for.la source