Was ist der Unterschied zwischen Reichweite und xrange Funktionen in Python 2.x?
-
01-07-2019 - |
Frage
Anscheinend ist xrange schneller, aber ich habe keine Ahnung, warum es schneller (und kein Beweis neben dem anekdotischen so weit, dass es schneller ist) oder, was neben dem ist etwas anderes über
for i in range(0, 20):
for i in xrange(0, 20):
Lösung
Bereich erstellt eine Liste, wenn Sie also range(1, 10000000)
tun erstellt er eine Liste im Speicher mit 9999999
Elementen.
xrange
ist ein Sequenz-Objekt, das träge auswertet.
Es sollte von @ Thiago des Hinweises hinzugefügt werden, dass in python3, Bereich tut das Äquivalent von Python xrange
Andere Tipps
Bereich erstellt eine Liste, wenn Sie also
range(1, 10000000)
tun erstellt er eine Liste im Speicher mit9999999
Elementen.
xrange
ist ein Generator, so dass era Objektsequenzist eindie lazily auswertet.
Das ist wahr, aber in Python 3 .range()
wird von dem Python 2 .xrange()
implementiert werden. Wenn Sie tatsächlich benötigen, um die Liste zu generieren, müssen Sie tun:
list(range(1,100))
Denken Sie daran, verwenden Sie das timeit
Modul zu testen, welche von kleinen Code-Schnipsel ist schneller!
$ 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 immer .range()
verwenden, es sei denn ich es zu tun hatten wirklich riesige Listen - wie Sie sehen können, zeitweise, für eine Liste von einer Million Einträgen, die zusätzlichen Aufwand ist nur 0,04 Sekunden. Und wie Corey weist darauf hin, in Python 3.0 .xrange()
weggeht und .range()
gibt Ihnen schönes Iterator Verhalten trotzdem.
xrange
speichert nur den Bereich params und erzeugt die Zahlen auf Anfrage. Jedoch ist die C-Implementierung von Python zur Zeit beschränkt seine args C longs:
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 in Python 3.0 gibt es nur range
und es verhält sich wie die 2.x xrange
aber ohne die Einschränkungen auf minimalen und maximalen Endpunkte.
xrange gibt einen Iterator und hält nur eine Zahl im Speicher zu einem Zeitpunkt. Bereich hält die gesamte Liste der Nummern im Speicher.
Sie verbringen einige Zeit mit dem Library Reference . Je vertrauter Sie mit ihm sind, desto schneller können Sie Antworten auf Fragen wie diese zu finden. Besonders wichtig sind die ersten Kapitel über gebautet Objekte und Typen.
Der Vorteil des xrange Typs ist, dass ein xrange Objekt wird immer nehmen Sie die gleiche Menge an Speicher, unabhängig von der Größe des Bereichs es darstellt. Es gibt keine konsistenten Performance-Vorteile.
Eine weitere Möglichkeit, schnell Informationen über ein Python-Konstrukt zu finden, ist das docstring und die Hilfe-Funktion:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Bereich erstellt eine Liste, wenn Sie also tun Bereich (1, 10 Millionen) erstellt es eine Liste im Speicher mit 10 Millionen Elementen. xrange ist ein Generator, so wertet er träge.
Das bringt Ihnen zwei Vorteile:
- Sie können mehr Listen durchlaufen, ohne eine
MemoryError
zu bekommen. - Wie es jede Zahl träge löst, wenn Sie früh stoppen Iteration, werden Sie nicht Zeit zu schaffen, die ganze Liste verschwenden.
Ich bin schockiert niemand lesen doc :
Diese Funktion ist sehr ähnlich zu
range()
, sondern gibt einxrange
Objekt statt einer Liste. Dies ist ein opaker Sequenztyp, die die gleichen Werte wie die entsprechenden Liste liefert, ohne tatsächlich sie alle gleichzeitig zu speichern. Der Vorteilxrange()
überrange()
ist minimal (daxrange()
hat immer noch die Werte zu schaffen, wenn sie danach gefragt werden), außer wenn ein sehr großer Bereich auf einem Speicher verhungert Maschine verwendet wird oder wenn alle Elemente des Bereichs niemals verwendet werden (wie zum Beispiel, wenn die Schleife in der Regel mitbreak
beendet).
Es ist aus Optimierungsgründen.
range () wird eine Liste von Werten vom Anfang bis zum Ende schaffen (0 .. 20 im Beispiel). Dies wird eine teuere Operation auf sehr großen Bereichen wird.
xrange () auf der anderen Seite ist viel mehr optimiert. es wird nur den nächsten Wert berechnen, wenn (über ein xrange Sequenzobjekt) benötigt und keine Liste aller Werte wie range () tut erstellen.
Sie werden den Vorteil xrange
über range
in diesem einfachen Beispiel finden:
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 hat nichts wesentlich besser bei xrange
widerspiegelt.
Jetzt im folgenden Fall schauen, wo range
wirklich langsam ist wirklich, im Vergleich zu xrange
.
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
, schafft bereits eine Liste 0-100.000.000 (zeitaufwendig), aber xrange
ist ein Generator und erzeugt nur Zahlen basierend auf der Notwendigkeit, das heißt, wenn die Iteration fortgesetzt wird.
In Python-3, die Umsetzung der range
Funktionalität ist das gleiche wie die von xrange
in Python-2, während sie mit xrange
in Python-3 getan haben, weg
Happy Coding !!
range ():. Bereich (1, 10) gibt eine Liste von 1 bis 10 Zahlen & ganze Liste im Speicher hält
xrange (): Wie range (), sondern statt dessen eine Liste zurückzugeben, gibt ein Objekt, das die Zahlen im Bereich bei Bedarf erzeugt. Für Looping ist dies leicht schneller als Bereich () und mehr Speicher effizienter zu gestalten. xrange () Objekt wie ein Iterator und erzeugt die Zahlen auf Anfrage. (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)
eine Liste von jeder Zahl gibt zwischen x und y, wenn Sie eine for
Schleife verwenden, dann ist range
langsamer. In der Tat hat range
einen größeren Index-Bereich. range(x.y)
wird eine Liste aller Zahlen zwischen x und y auszudrucken
xrange(x,y)
kehrt xrange(x,y)
aber wenn Sie eine for
Schleife verwendet, dann xrange
ist schneller. xrange
hat einen kleineren Indexbereich. xrange
wird nicht nur xrange(x,y)
ausdrucken, aber es wird immer noch alle Zahlen halten, die in ihm sind.
[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, dann würde es 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 nicht viel Unterschied, wenn Schleifen verwenden, obwohl es einen Unterschied ist beim Drucken es einfach!
In Python 2.x
Bereich (x) gibt eine Liste, die im Speicher mit x Elementen erstellt wird.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) gibt ein xrange Objekt, das einen Generator obj ist, die die Zahlen auf Nachfrage erzeugt. sie berechnet werden während der for-Schleife (lazy evaluation).
Für Looping, dies ist etwas schneller als range () und mehr Speicher effizienter zu gestalten.
>>> b = xrange(5)
>>> b
xrange(5)
Bei der Prüfung Bereich gegen xrange in einer Schleife (ich weiß, soll ich verwenden timeit , aber das wurde schnell gehackt aus dem Speicher ein einfaches Liste Verständnis am Beispiel) ich fand die folgende:
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)
das 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 mit 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? Eventuelle Stellungnahmen der langsamen Instanz xrange? Oder ein besseres Beispiel: -)
Einige der anderen Antworten erwähnt, dass Python 3 2.x des range
eliminiert und xrange
des umbenannt 2.x auf range
. Allerdings, wenn Sie 3.0 oder 3.1 verwenden (was niemand sein sollte), ist es eigentlich eine etwas andere Art.
Wie die 3.1 docs sagen:
Range-Objekte haben sehr wenig Verhalten: sie nur Indizierung unterstützen, Iteration und die
.len
Funktion
Doch in 3.2+, range
ist eine vollständige sequenz es erweitert Scheiben unterstützt, und alle Methoden von collections.abc.Sequence
mit der gleichen Semantik als list
. *
Und zumindest in CPython und PyPy (die einzigen zwei 3.2+ Implementierungen, die derzeit vorhanden ist), hat es auch konstante Zeit Implementierungen der index
und count
Methoden und den in
Operators (solange man nur gibt es ganze Zahlen) . Das bedeutet, das Schreiben 123456 in r
in 3.2+ sinnvoll ist, während in 2.7 oder 3.1 es eine schreckliche Idee.
* Die Tatsache, dass issubclass(xrange, collections.Sequence)
kehrt True
in 2,6-2,7 und 3,0-3,1 ist einen Fehler das wurde in 3.2 und nicht.
xrange () und range () in Python ähnlich wie für den Benutzer funktioniert, aber der Unterschied kommt, wenn wir reden, wie der Speicher in Verwendung sowohl die Funktion zugeordnet ist.
Wenn wir Bereich () verwenden wir weisen Speicher für alle Variablen es erzeugt, so ist es nicht empfehlenswert mit größeren verwenden nicht. von Variablen erzeugt werden.
xrange () auf der anderen Seite erzeugt nur einen bestimmten Wert zu einem Zeitpunkt und kann nur mit der for-Schleife verwendet werden, um alle Werte zu drucken, benötigt.
Bereich erzeugt die gesamte Liste und gibt es zurück. xrange nicht -. es die Zahlen in der Liste auf Nachfrage erzeugt
Lesen Sie den folgenden Beitrag für den Vergleich zwischen Reichweite und xrange mit grafischer Auswertung.
xrange verwendet einen Iterator (erzeugt Werte on the fly), Bereich gibt eine Liste.
Was?
range
gibt eine statische Liste zur Laufzeit.
xrange
gibt eine object
(die wie ein Generator wirkt, obwohl es ist sicherlich nicht ein), aus denen Werte erzeugt werden und bei Bedarf.
Wann welche?
- Verwenden Sie
xrange
wenn Sie eine Liste für einen gigantischen Bereich generieren wollen, sagen 1000000000, vor allem, wenn Sie ein „Gedächtnis sensibles System“ haben wie ein Handy. - Verwenden Sie
range
, wenn Sie über die Liste mehrmals wiederholen wollen.
PS:. range
Funktion des Python 3.x == Python 2.x des xrange
Funktion
Auf einer Anforderung für das Scannen / Drucken von 0-N Produkte, Reichweite und xrange funktioniert wie folgt.
range () - erzeugt eine neue Liste im Speicher und nimmt die ganzen 0 bis N Artikel (total N + 1) und druckt sie. xrange (.) - erzeugt eine Iterator-Instanz, die die Elemente durchsucht und hält nur die aktuellen angetroffen Artikel in den Speicher, damit gleiche Menge an Speichern die ganze Zeit unter Verwendung
Falls das gewünschte Element ist etwas am Anfang der Liste nur dann speichert es eine gute Menge an Zeit und Speicher.
Der Unterschied verringert sich für kleinere Argumente / range(..)
xrange(..)
:
$ 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 xrange(100)
ist nur etwa 20% effizienter.
Jeder hat es stark erläutert. Aber ich wollte es für mich zu sehen. Ich benutze python3. Also öffnete ich den Ressourcenmonitor (in Windows!), Und zuerst ausgeführt, um den folgenden Befehl zuerst:
a=0
for i in range(1,100000):
a=a+i
und überprüft dann die Änderung in 'In Use' Speicher. Es war unbedeutend. Dann lief ich den folgenden Code:
for i in list(range(1,100000)):
a=a+i
Und es nahm einen großen Teil des Speichers für den Einsatz, sofort. Und ich war überzeugt. Sie können es selbst ausprobieren.
Wenn Sie Python 2X verwenden, dann ersetzen 'range ()' mit 'xrange ()' in dem ersten Code und Liste (range ()) "mit 'range ()'.
Bereich liefert a Liste während xrange Gibt ein xrange Objekt, das unabhängig von dem Bereich den gleichen Speicher nimmt Größe, wie in diesem Fall wird nur ein Element pro Iteration erzeugt und zur Verfügung, während im Falle der Bereich verwendet wird, werden alle Elemente auf einmal erzeugt und in dem Speicher zur Verfügung.
Bereich: -Reihe wird alles bevölkern bei once.which jede Zahl des Bereichs bedeutet, dass die Speicher belegen
.xrange: -xrange ist so etwas wie Generator, wird es ins Bild kommt, wenn Sie den Zahlenbereich wollen aber Sie nicht wollen, dass sie gespeichert werden, wie wenn man effizient für loop.so Speicher verwenden, in möchten
Von der Hilfe-Dokumentation.
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 range
eine Liste, xrange
gibt ein xrange Objekt, das iterable ist.
In Python 3.x wird range
xrange
von Python 2.x und xrange
entfernt wird.
Außerdem, wenn list(xrange(...))
tun, um range(...)
gleichwertig sein.
So list
ist langsam.
xrange
auch wirklich nicht vollständig die Sequenz nicht beenden
Also, warum es nicht eine Liste, es ist ein xrange
Objekt
Sehen Sie diese Post Unterschied zwischen Bereich zu finden und xrange :
Zitat:
range
liefert genau das, was Sie denken: eine Liste aufeinanderfolgender ganze Zahlen, mit definierter Länge, beginnend mit 0xrange
jedoch gibt ein "xrange Objekt" , die viel wie ein Iterator fungiert