web-dev-qa-db-de.com

Was ist der Unterschied zwischen Range- und Xrange-Funktionen in Python 2.X?

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):
644
Teifion

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 

735
Charles

bereich erstellt eine Liste. Wenn Sie range(1, 10000000) tun, wird eine Liste mit 9999999-Elementen im Speicher erstellt.

xrange ist ein Generator, also ist ein Sequenzobjekt ist ein das 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))
215
Corey

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.

103
John Fouhy

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.

64
efotinis

xrange gibt einen Iterator zurück und speichert immer nur eine Nummer im Speicher. Bereich hält die gesamte Liste der Nummern im Speicher.

38
Ben Hoffstein

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)
28
Antti Rasinen

Ich bin schockiert, dass niemand gelesen hat doc :

Diese Funktion ist range() sehr ähnlich, gibt jedoch ein xrange-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 von xrange() gegenüber range() ist minimal (da xrange() 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 mit break) abgeschlossen.

13
Kishor Pawar

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:

  1. Sie können längere Listen durchlaufen, ohne eine MemoryError zu erhalten.
  2. Da jede Zahl träge aufgelöst wird, verschwenden Sie keine Zeit, wenn Sie die Iteration vorzeitig beenden.
12
Lucas S.

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.

10
QAZ

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 !! 

10
User_Targaryen

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
8
Tushar.PUCSD

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!

8
Supercolbat

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)
6
SrmHitter9062

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 :-)

5
Dave Everitt

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.

5
abarnert

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.

4

Lesen Sie den folgenden Beitrag zum Vergleich zwischen Bereich und Bereich mit grafischer Analyse.

Pythonbereich Vs xrange

3
Harsha Vardhan

range generiert die gesamte Liste und gibt sie zurück. xrange nicht - es generiert die Nummern in der Liste bei Bedarf.

3
Eddie Deyo

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? 

  • Verwenden Sie 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.
  • Verwenden Sie range, wenn Sie die Liste mehrmals durchlaufen möchten.

PS: Python 3.xs range-Funktion == Python 2.xs xrange-Funktion.

2
kmario23

xrange verwendet einen Iterator (erzeugt schnell Werte), range gibt eine Liste zurück.

2
hacama

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.

1
Evgeni Sergeev

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.

1
SomeDoubts

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 ()'.

1
ANKUR SATYA

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.

0
Rajendra Uppal

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.

0
user299567

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.

0
tejaswini teju

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

0
U9-Forward