Anscheinend ist Xrange schneller, aber ich habe keine Ahnung, warum es schneller ist (und abgesehen von der Anekdote keinen Beweis, dass es schneller ist) oder was darüber hinaus anders ist
for i in range(0, 20):
for i in xrange(0, 20):
bereich erstellt eine Liste. Wenn Sie range(1, 10000000)
tun, wird eine Liste mit 9999999
-Elementen im Speicher erstellt.
xrange
ist ein Sequenzobjekt, das träge ausgewertet wird.
Es sollte aus dem Hinweis von @ Thiago hinzugefügt werden, dass der Bereich in python3 dem Äquivalent von pythons Xrange entspricht
bereich erstellt eine Liste. Wenn Sie
range(1, 10000000)
tun, wird eine Liste mit9999999
-Elementen im Speicher erstellt.
xrange
ist ein Generator, alsoist ein Sequenzobjektist eindas bewertet faul.
Dies ist wahr, aber in Python 3 wird .range()
von Python 2 .xrange()
implementiert. Wenn Sie die Liste tatsächlich erstellen müssen, müssen Sie Folgendes tun:
list(range(1,100))
Denken Sie daran, verwenden Sie das Modul timeit
, um zu testen, welcher Code-Schnipsel schneller ist!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
Ich persönlich benutze immer .range()
, es sei denn, ich habe es mit wirklich riesigen Listen zu tun. Wie Sie zeitlich für eine Liste mit einer Million Einträgen sehen können, beträgt der zusätzliche Aufwand nur 0,04 Sekunden. Und wie Corey darauf hinweist, wird .xrange()
in Python 3.0 verschwinden und .range()
wird Ihnen trotzdem ein schönes Iterator-Verhalten geben.
xrange
speichert nur die Bereichsparameter und generiert die Nummern bei Bedarf. Die C-Implementierung von Python beschränkt jedoch derzeit seine Argumente auf C-Längen:
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Beachten Sie, dass es in Python 3.0 nur range
gibt und dass es sich wie 2.x xrange
verhält, jedoch ohne die Begrenzungen der minimalen und maximalen Endpunkte.
xrange gibt einen Iterator zurück und speichert immer nur eine Nummer im Speicher. Bereich hält die gesamte Liste der Nummern im Speicher.
Verbringen Sie etwas Zeit mit der Library Reference . Je vertrauter Sie damit sind, desto schneller finden Sie Antworten auf solche Fragen. Besonders wichtig sind die ersten Kapitel über eingebaute Objekte und Typen.
Der Vorteil des Xrange-Typs besteht darin, dass ein Xrange-Objekt immer Nehmen Sie dieselbe Menge an Speicherplatz in Anspruch, unabhängig von der Größe des Bereichs, den er darstellt. Es gibt keine konsistenten Leistungsvorteile.
Eine andere Möglichkeit, schnelle Informationen zu einem Python-Konstrukt zu finden, ist der docstring und die help-Funktion:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Ich bin schockiert, dass niemand gelesen hat doc :
Diese Funktion ist
range()
sehr ähnlich, gibt jedoch einxrange
-Objekt anstelle einer Liste zurück. Dies ist ein undurchsichtiger Sequenztyp, der dieselben Werte wie die entsprechende Liste liefert, ohne sie alle gleichzeitig zu speichern. Der Vorteil vonxrange()
gegenüberrange()
ist minimal (daxrange()
noch die Werte erstellen muss, wenn Sie dazu aufgefordert werden), es sei denn, ein sehr großer Bereich wird auf einer speicherintensiven Maschine verwendet oder wenn alle Elemente des Bereichs niemals verwendet werden (z Die Schleife wird normalerweise mitbreak
) abgeschlossen.
range erstellt eine Liste. Wenn Sie also range (1, 10000000) verwenden, wird im Speicher eine Liste mit 10000000 Elementen ..__ erstellt. xrange ist ein Generator und wird daher faul bewertet.
Das bringt Ihnen zwei Vorteile:
MemoryError
zu erhalten.Es ist aus Optimierungsgründen.
range () erstellt eine Liste mit Werten von Anfang bis Ende (0 bis 20 in Ihrem Beispiel). Dies wird bei sehr großen Reichweiten zu einem teuren Vorgang.
xrange () ist dagegen viel mehr optimiert. Es berechnet den nächsten Wert nur bei Bedarf (über ein Xrange-Sequenzobjekt) und erstellt keine Liste aller Werte, wie dies bei range () der Fall ist.
Den Vorteil von xrange
gegenüber range
finden Sie in diesem einfachen Beispiel:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
Das obige Beispiel spiegelt im Fall von xrange
nichts wesentlich besseres wider.
Betrachten Sie nun den folgenden Fall, in dem range
im Vergleich zu xrange
wirklich sehr langsam ist.
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
Mit range
wird bereits eine Liste von 0 bis 100000000 erstellt (zeitaufwendig), xrange
ist jedoch ein Generator und generiert nur Zahlen basierend auf der Notwendigkeit, d. H.
In Python-3 stimmt die Implementierung der range
-Funktionalität mit der von xrange
in Python-2 überein, während in Python-3 auf xrange
verzichtet wurde
Viel Spaß beim Codieren !!
range (): range (1, 10) gibt eine Liste von 1 bis 10 Zahlen zurück und hält die gesamte Liste im Speicher.
xrange (): Wie range (), gibt jedoch anstelle einer Liste ein Objekt zurück, das die Zahlen im Bereich bei Bedarf generiert. Für das Looping ist dies etwas schneller als range () und speichereffizienter . xrange () - Objekt wie ein Iterator und generiert die Zahlen bei Bedarf. (Lazy Evaluation)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
range(x,y)
gibt eine Liste aller Zahlen zwischen x und y zurück, wenn Sie eine for
-Schleife verwenden. Dann ist range
langsamer. Tatsächlich hat range
einen größeren Indexbereich. range(x.y)
druckt eine Liste aller Zahlen zwischen x und y aus
xrange(x,y)
gibt xrange(x,y)
zurück. Wenn Sie jedoch eine for
-Schleife verwenden, ist xrange
schneller. xrange
hat einen kleineren Indexbereich. xrange
druckt nicht nur xrange(x,y)
aus, sondern behält auch alle darin enthaltenen Zahlen.
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
Wenn Sie eine for
-Schleife verwenden, würde sie funktionieren
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
Es gibt keinen großen Unterschied beim Verwenden von Schleifen, obwohl beim Drucken nur ein Unterschied besteht!
In Python 2.x
range (x) gibt eine Liste zurück, die im Speicher mit x Elementen erstellt wird.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) gibt ein Xrange-Objekt zurück, bei dem es sich um einen Generator obj handelt, der die Zahlen bei Bedarf generiert. Sie werden während der for-loop (Lazy Evaluation) berechnet.
Für das Looping ist dies etwas schneller als range () und speichereffizienter.
>>> b = xrange(5)
>>> b
xrange(5)
Beim Testen des Bereichs gegen Xrange in einer Schleife (ich weiß, dass ich timeit verwenden sollte, aber dies wurde schnell aus dem Speicher gehackt, wobei ein einfaches Listenverständnisbeispiel verwendet wurde), fand ich Folgendes:
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
was gibt:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
Oder verwenden Sie xrange in der for-Schleife:
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
Ist mein Snippet-Test richtig? Anmerkungen zur langsameren Instanz von xrange? Oder ein besseres Beispiel :-)
Einige der anderen Antworten erwähnen, dass Python 3 range
von 2.x eliminierte und xrange
von 2.x in range
umbenannte. Wenn Sie jedoch nicht 3.0 oder 3.1 verwenden (was keiner sein sollte), handelt es sich tatsächlich um einen etwas anderen Typ.
Wie die 3.1 Dokumente sagen:
Bereichsobjekte haben ein sehr geringes Verhalten: Sie unterstützen nur die Indizierung, die Iteration und die Funktion
len
.
In Version 3.2+ ist range
jedoch eine vollständige Sequenz, die erweiterte Slices und alle Methoden von collections.abc.Sequence
mit derselben Semantik wie eine list
unterstützt.*
Zumindest in CPython und PyPy (den einzigen zwei 3.2+ -Implementierungen, die derzeit existieren) gibt es auch Konstant-Implementierungen der Methoden index
und count
und des in
-Operators (solange Sie nur Ganzzahlen übergeben). Dies bedeutet, dass das Schreiben von 123456 in r
in 3.2+ sinnvoll ist, während es in 2.7 oder 3.1 eine schreckliche Idee wäre.
* Die Tatsache, dass issubclass(xrange, collections.Sequence)
True
in 2.6-2.7 und 3.0-3.1 zurückgibt, ist ein Fehler der in 3.2 behoben wurde und nicht zurückportiert wurde.
xrange () und range () funktionieren in Python ähnlich wie für den Benutzer. Der Unterschied besteht jedoch, wenn wir darüber sprechen, wie der Speicher mit beiden Funktionen belegt wird.
Wenn Sie range () verwenden, weisen wir Speicher für alle Variablen zu, die generiert werden. Es wird daher nicht empfohlen, die Verwendung von größer (Nein) zu verwenden. der zu generierenden Variablen.
xrange () hingegen erzeugt jeweils nur einen bestimmten Wert und kann nur mit der for-Schleife verwendet werden, um alle erforderlichen Werte zu drucken.
Lesen Sie den folgenden Beitrag zum Vergleich zwischen Bereich und Bereich mit grafischer Analyse.
range generiert die gesamte Liste und gibt sie zurück. xrange nicht - es generiert die Nummern in der Liste bei Bedarf.
Was?range
gibt zur Laufzeit eine statische Liste zurück.xrange
gibt eine object
zurück (die sich wie ein Generator verhält, obwohl es sicherlich kein Generator ist), aus dem Werte nach Bedarf generiert werden.
Wann welche verwenden?
xrange
, wenn Sie eine Liste für einen gigantischen Bereich erstellen möchten, beispielsweise 1 Milliarde, insbesondere wenn Sie ein "speicherempfindliches System" wie ein Mobiltelefon haben.range
, wenn Sie die Liste mehrmals durchlaufen möchten.PS: Python 3.xs range
-Funktion == Python 2.xs xrange
-Funktion.
xrange verwendet einen Iterator (erzeugt schnell Werte), range gibt eine Liste zurück.
Der Unterschied nimmt bei kleineren Argumenten zu range(..)
/xrange(..)
ab:
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
In diesem Fall ist xrange(100)
nur etwa 20% effizienter.
Bei einer Anforderung zum Scannen/Drucken von 0-N-Sendungen funktionieren range und xrange wie folgt.
range () - erstellt eine neue Liste im Speicher und bringt die gesamten 0 bis N Elemente (total N + 1) und druckt diese aus xrange () - erstellt eine Iterator-Instanz, die die Elemente durchsucht und nur das aktuelle enthält Element in den Speicher gefunden, daher immer die gleiche Menge an Speicher verwendet.
Befindet sich das benötigte Element nur etwas am Anfang der Liste, spart es viel Zeit und Speicherplatz.
Jeder hat es großartig erklärt. Aber ich wollte es für mich selbst sehen. Ich benutze Python3. Also habe ich den Ressourcenmonitor (in Windows!) Geöffnet und zuerst den folgenden Befehl ausgeführt:
a=0
for i in range(1,100000):
a=a+i
und überprüfte dann die Änderung im Arbeitsspeicher. Es war unbedeutend ..__ Dann habe ich den folgenden Code ausgeführt:
for i in list(range(1,100000)):
a=a+i
Und es brauchte sofort einen großen Teil des Speichers. Und ich war überzeugt ... Sie können es selbst ausprobieren.
Wenn Sie Python 2X verwenden, ersetzen Sie 'range ()' durch 'xrange ()' im ersten Code und 'list (range ())' durch 'range ()'.
Aus den Hilfedokumenten.
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
Der Unterschied ist offensichtlich. In Python 2.x gibt range
eine Liste zurück, xrange
gibt ein Xrange-Objekt zurück, das iterierbar ist.
In Python 3.x wird range
zu xrange
von Python 2.x und xrange
wird entfernt.
Range gibt eine Liste zurück, während xrange ein xrange - Objekt zurückgibt, das unabhängig von der Bereichsgröße denselben Speicher belegt, da in diesem Fall nur ein Element erzeugt wird und pro Element verfügbar ist Iteration, während bei der Verwendung von range alle Elemente gleichzeitig generiert werden und im Speicher verfügbar sind.
range: -range füllt alles auf einmal aus. Dies bedeutet, dass jede Nummer des Bereichs den Speicher belegt.
xrange: -xrange ist so etwas wie ein Generator. Er erscheint im Bild, wenn Sie den Zahlenbereich wünschen, aber nicht möchten, dass sie gespeichert werden, z.
Außerdem ist if list(xrange(...))
gleichbedeutend mit range(...)
.
list
ist also langsam.
Auch xrange
beendet die Sequenz wirklich nicht vollständig
Deshalb ist es keine Liste, sondern ein xrange
Objekt