Neulich habe ich Python-Benchmarking durchgeführt und bin auf etwas Interessantes gestoßen. Unten sind zwei Schleifen aufgeführt, die mehr oder weniger dasselbe tun. Die Ausführung von Schleife 1 dauert ungefähr doppelt so lange wie Schleife 2.
Schleife 1:
int i = 0
while i < 100000000:
i += 1
Schleife 2:
for n in range(0,100000000):
pass
Warum ist die erste Schleife so viel langsamer? Ich weiß, dass es ein triviales Beispiel ist, aber es hat mein Interesse geweckt. Gibt es etwas Besonderes an der Funktion range (), das sie effizienter macht als das Inkrementieren einer Variablen auf dieselbe Weise?
quelle
while
Schleife bei jeder Iteration einen Vergleich durchführen muss?range()
wird in C implementiert, währendi += 1
interpretiert wird.Die Verwendung
xrange()
könnte es für große Zahlen noch schneller machen. Das Starten mit Python 3.0range()
ist das gleiche wie zuvorxrange()
.quelle
Es muss gesagt werden, dass mit der while-Schleife viel Objekt erstellt und zerstört wird.
i += 1
ist das gleiche wie:
i = i + 1
Da Python-Ints jedoch unveränderlich sind, wird das vorhandene Objekt nicht geändert. Vielmehr entsteht ein brandneues Objekt mit einem neuen Wert. Es ist im Grunde:
i = new int(i + 1) # Using C++ or Java-ish syntax
Der Garbage Collector muss auch eine große Menge an Aufräumarbeiten durchführen. "Objekterstellung ist teuer".
quelle
Weil Sie häufiger mit Code arbeiten, der im Interpretor in C geschrieben ist. dh i + = 1 ist in Python so langsam (vergleichsweise), während der Bereich (0, ...) ein C-Aufruf ist, den die for-Schleife meistens auch in C ausführt.
quelle
Die meisten in Python integrierten Methodenaufrufe werden als C-Code ausgeführt. Code, der interpretiert werden muss, ist viel langsamer. In Bezug auf Speichereffizienz und Ausführungsgeschwindigkeit ist der Unterschied gigantisch. Die Python-Interna wurden extrem optimiert, und es ist am besten, diese Optimierungen zu nutzen.
quelle
Ich denke, die Antwort hier ist etwas subtiler als die anderen Antworten vermuten lassen, obwohl das Wesentliche richtig ist: Die for-Schleife ist schneller, weil mehr Operationen in C und weniger in Python stattfinden .
Im Fall der for-Schleife passieren in C zwei Dinge, die in der while-Schleife in Python behandelt werden:
In der while-Schleife wird der Vergleich
i < 100000000
in Python ausgeführt, während in der for-Schleife der Job an den Iterator von übergeben wirdrange(100000000)
, der intern die Iteration (und damit die Überprüfung der Grenzen) in C durchführt.In der while-Schleife erfolgt die Aktualisierung der Schleife
i += 1
in Python, während in der for-Schleife derrange(100000000)
in C geschriebene Iterator voni+=1
(oder++i
) erneut ausgeführt wird.Wir können sehen, dass es eine Kombination dieser beiden Dinge ist, die die for-Schleife schneller macht, indem sie manuell wieder hinzugefügt werden, um den Unterschied zu erkennen.
import timeit N = 100000000 def while_loop(): i = 0 while i < N: i += 1 def for_loop_pure(): for i in range(N): pass def for_loop_with_increment(): for i in range(N): i += 1 def for_loop_with_test(): for i in range(N): if i < N: pass def for_loop_with_increment_and_test(): for i in range(N): if i < N: pass i += 1 def main(): print('while loop\t\t', timeit.timeit(while_loop, number=1)) print('for pure\t\t', timeit.timeit(for_loop_pure, number=1)) print('for inc\t\t\t', timeit.timeit(for_loop_with_increment, number=1)) print('for test\t\t', timeit.timeit(for_loop_with_test, number=1)) print('for inc+test\t', timeit.timeit(for_loop_with_increment_and_test, number=1)) if __name__ == '__main__': main()
Ich habe dies sowohl mit der Zahl 100000000 als Literalkonstante als auch mit einer Variablen versucht,
N
wie es typischer wäre.# inline constant N while loop 3.5131139 for pure 1.3211338000000001 for inc 3.5477727000000003 for test 2.5209639 for inc+test 4.697028999999999 # variable N while loop 4.1298240999999996 for pure 1.3526357999999998 for inc 3.6060175 for test 3.1093069 for inc+test 5.4753364
Wie Sie sehen können, liegt die
while
Zeit in beiden Fällen sehr nahe am Unterschied vonfor inc+test
undfor pure
. Beachten Sie auch, dass in dem Fall, in dem wir dieN
Variable verwenden, diewhile
eine zusätzliche Verlangsamung aufweist, um den Wert von wiederholt nachzuschlagenN
, diefor
jedoch nicht.Es ist wirklich verrückt, dass solche trivialen Änderungen zu einer über 3-fachen Code-Beschleunigung führen können , aber das ist Python für Sie. Und lass mich nicht einmal anfangen, wenn du überhaupt ein eingebautes über eine Schleife verwenden kannst ...
quelle