Einige Leistungsmessungen verwenden, timeitanstatt zu versuchen, dies manuell zu tun time.
Zunächst Apple 2.7.2 64-Bit:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop
Jetzt python.org 3.3.0 64-Bit:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop
In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop
In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.33 s per loop
Offenbar 3.x rangeist wirklich ein bisschen langsamer als 2.x xrange. Und die xrangeFunktion des OP hat nichts damit zu tun. (Kein Wunder, da ein einmaliger Anruf an den __iter__Slot unter 10000000 Anrufen für alles, was in der Schleife passiert, wahrscheinlich nicht sichtbar ist, aber jemand hat ihn als Möglichkeit angesprochen.)
Aber es ist nur 30% langsamer. Wie wurde das OP 2x so langsam? Wenn ich die gleichen Tests mit 32-Bit-Python wiederhole, erhalte ich 1,58 gegenüber 3,12. Ich vermute also, dass dies ein weiterer Fall ist, in dem 3.x für 64-Bit-Leistung in einer Weise optimiert wurde, die 32-Bit-Leistung beeinträchtigt.
Aber ist das wirklich wichtig? Überprüfen Sie dies mit 3.3.0 64-Bit erneut:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop
Das Erstellen von listdauert also mehr als doppelt so lange wie die gesamte Iteration.
Und was "verbraucht viel mehr Ressourcen als Python 2.6+" betrifft, so sieht es aus meinen Tests so aus, als ob ein 3.x rangegenau die gleiche Größe wie ein 2.x hat xrange- und selbst wenn es 10x so groß wäre, die unnötige Liste erstellt ist immer noch ungefähr 10000000x mehr ein Problem als alles, was die Bereichsiteration möglicherweise tun könnte.
Und was ist mit einer expliziten forSchleife anstelle der C-Schleife im Inneren deque?
In [87]: def consume(x):
....: for i in x:
....: pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop
Es wurde also fast so viel Zeit in der forAussage verschwendet wie in der eigentlichen Arbeit der Iteration der range.
Wenn Sie sich Gedanken über die Optimierung der Iteration eines Bereichsobjekts machen, suchen Sie wahrscheinlich an der falschen Stelle.
In der Zwischenzeit fragen Sie immer wieder, warum xrangeentfernt wurde, egal wie oft Ihnen die Leute dasselbe sagen, aber ich werde es noch einmal wiederholen: Es wurde nicht entfernt: Es wurde umbenannt in rangeund das 2.x rangewurde entfernt.
Hier ist ein Beweis dafür, dass das 3.3- rangeObjekt ein direkter Nachkomme des 2.x- xrangeObjekts (und nicht der 2.x- rangeFunktion) ist: die Quelle für 3.3range und 2.7xrange . Sie können sogar den Änderungsverlauf sehen (der meiner Meinung nach mit der Änderung verknüpft ist, die die letzte Instanz der Zeichenfolge "xrange" an einer beliebigen Stelle in der Datei ersetzt hat).
Warum ist es langsamer?
Zum einen haben sie viele neue Funktionen hinzugefügt. Zum anderen haben sie überall alle Arten von Änderungen vorgenommen (insbesondere innerhalb der Iteration), die geringfügige Nebenwirkungen haben. Und es gab viel Arbeit, um verschiedene wichtige Fälle dramatisch zu optimieren, auch wenn es manchmal weniger wichtige Fälle leicht pessimiert. Addiere das alles und ich bin nicht überrascht, dass das Iterieren eines rangeso schnellen wie möglich jetzt etwas langsamer ist. Es ist einer dieser weniger wichtigen Fälle, auf die sich niemand jemals genug konzentrieren würde. Es ist wahrscheinlich, dass niemand jemals einen realen Anwendungsfall hat, bei dem dieser Leistungsunterschied der Hotspot in seinem Code ist.
rangein Python 3.x istxrangevon Python 2.x. Es war tatsächlich Python 2.x,rangedas entfernt wurde.