Das Folgende sind grobe Richtlinien und fundierte Vermutungen, die auf Erfahrung basieren. Du solltesttimeit
oder profilieren Sie Ihren konkreten Anwendungsfall, um harte Zahlen zu erhalten, und diese Zahlen stimmen gelegentlich nicht mit den folgenden überein.
Ein Listenverständnis ist normalerweise ein kleines bisschen schneller als die genau äquivalente for
Schleife (die tatsächlich eine Liste erstellt), höchstwahrscheinlich, weil die Liste und ihre append
Methode nicht bei jeder Iteration nachgeschlagen werden müssen. Ein Listenverständnis führt jedoch immer noch eine Schleife auf Bytecode-Ebene durch:
>>> 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
Die Verwendung eines Listenverständnisses anstelle einer Schleife, die keine Liste erstellt, eine Liste mit bedeutungslosen Werten unsinnig ansammelt und die Liste dann wegwirft, ist häufig langsamer, da das Erstellen und Erweitern der Liste aufwändig ist. Listenverständnisse sind keine Magie, die von Natur aus schneller ist als eine gute alte Schleife.
Funktionsverarbeitungslisten: Während diese in C geschrieben sind und wahrscheinlich die in Python geschriebenen äquivalenten Funktionen übertreffen, sind sie nicht unbedingt die schnellste Option. Eine gewisse Beschleunigung wird erwartet, wenn die Funktion auch in C geschrieben ist. In den meisten Fällen, in denen eine lambda
(oder eine andere Python-Funktion) verwendet wird, führt der Aufwand für das wiederholte Einrichten von Python-Stack-Frames usw. zu Einsparungen. Die gleiche Arbeit inline ohne Funktionsaufrufe (z. B. ein Listenverständnis anstelle von map
oder filter
) zu erledigen, ist oft etwas schneller.
Angenommen, ich muss in einem Spiel, das ich entwickle, komplexe und riesige Karten mit for-Schleifen zeichnen. Diese Frage wäre definitiv relevant, denn wenn beispielsweise ein Listenverständnis tatsächlich schneller ist, wäre es eine viel bessere Option, um Verzögerungen zu vermeiden (trotz der visuellen Komplexität des Codes).
Wenn Code wie dieser nicht bereits schnell genug ist, wenn er in gutem, nicht "optimiertem" Python geschrieben ist, wird er wahrscheinlich durch keine Mikrooptimierung auf Python-Ebene schnell genug, und Sie sollten darüber nachdenken, auf C zu fallen Mikrooptimierungen können Python-Code oft erheblich beschleunigen, es gibt eine niedrige (in absoluten Zahlen) Grenze dafür. Darüber hinaus wird es noch kostengünstiger (15% Beschleunigung gegenüber 300% Beschleunigung bei gleichem Aufwand), die Kugel zu beißen und etwas C zu schreiben, noch bevor Sie diese Obergrenze erreichen.
Sie fragen gezielt nach
map()
,filter()
undreduce()
, aber ich nehme an, Sie über funktionale Programmierung im Allgemeinen wissen wollen. Nachdem ich dies selbst auf das Problem der Berechnung der Abstände zwischen allen Punkten innerhalb einer Reihe von Punkten getestet hatte, stellte sich heraus, dass die funktionale Programmierung (unter Verwendung derstarmap
Funktion des eingebautenitertools
Moduls) etwas langsamer war als die for-Schleifen (die 1,25-mal so lange dauerte) Tatsache). Hier ist der Beispielcode, den ich verwendet habe:Ist die funktionale Version schneller als die prozedurale Version?
quelle
Ich habe ein einfaches Skript geschrieben, das die Geschwindigkeit testet, und das habe ich herausgefunden. Eigentlich war for loop in meinem Fall am schnellsten. Das hat mich wirklich überrascht, schau unten (berechnete die Summe der Quadrate).
quelle
int
Insquare_sum4
macht es auch ziemlich viel schneller und nur ein bisschen langsamer als die for-Schleife.Wenn Sie der Alphii-Antwort eine Wendung hinzufügen , ist die for-Schleife die zweitbeste und ungefähr sechsmal langsamer als
map
Die wichtigsten Änderungen bestanden darin, die langsamen
sum
Anrufe sowie dieint()
im letzten Fall wahrscheinlich unnötigen zu beseitigen . Wenn Sie die for-Schleife und die Map in die gleichen Begriffe setzen, ist dies tatsächlich eine Tatsache. Denken Sie daran, dass Lambdas funktionale Konzepte sind und theoretisch keine Nebenwirkungen haben sollten, aber sie können Nebenwirkungen wie das Hinzufügen zu habena
. Ergebnisse in diesem Fall mit Python 3.6.1, Ubuntu 14.04, Intel (R) Core (TM) i7-4770-CPU bei 3,40 GHzquelle
Ich habe den Code von @ Alisa geändert und
cProfile
gezeigt, warum das Listenverständnis schneller ist:Hier sind die Ergebnisse:
MEINER BESCHEIDENEN MEINUNG NACH:
reduce
undmap
sind im Allgemeinen ziemlich langsam. Darüber hinaus ist die Verwendungsum
der zurückgegebenen Iteratoren immap
Vergleich zusum
einer Liste langsamfor_loop
verwendet append, was natürlich bis zu einem gewissen Grad langsam istsum
im Gegensatz zu auch viel schnellermap
quelle
Ich habe es geschafft, einen Teil des Codes von @ alpiii zu ändern und festgestellt, dass das Listenverständnis etwas schneller ist als für die Schleife. Es kann durch verursacht werden
int()
, es ist nicht fair zwischen Listenverständnis und for-Schleife.quelle