Frage

Warum oder warum nicht?

War es hilfreich?

Lösung

Für Leistung, vor allem, wenn Sie über einen großen Bereich sind laufen, ist xrange() in der Regel besser. Allerdings gibt es noch ein paar Fälle, warum Sie range() bevorzugen:

  • In Python 3, range() tut, was xrange() verwendet zu tun und xrange() existiert nicht. Wenn Sie Code schreiben möchten, 3 sowohl Python 2 und Python ausgeführt wird, können Sie nicht xrange() verwenden.

  • range() kann tatsächlich schneller in einigen Fällen - zB. wenn über die gleiche Sequenz mehrmals iteriert. xrange() hat die ganze Zahl Objekt jedes Mal zu rekonstruieren, aber range() werden echte Integer-Objekte haben. (Es wird immer schlechter ab in Bezug auf Speicher jedoch)

  • xrange() ist nicht in allen Fällen einsetzbar, wo eine echte Liste benötigt wird. Zum Beispiel unterstützt es nicht Scheiben oder keine Liste Methoden.

[Bearbeiten] Es gibt ein paar Beiträge zu erwähnen, wie range() wird von dem 2to3-Tool aktualisiert werden. Für die Aufzeichnung ist hier die Ausgabe des Werkzeugs auf einige Beispielverwendungen von range() des Laufens und xrange()

RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: ws_comma
--- range_test.py (original)
+++ range_test.py (refactored)
@@ -1,7 +1,7 @@

 for x in range(20):
-    a=range(20)
+    a=list(range(20))
     b=list(range(20))
     c=[x for x in range(20)]
     d=(x for x in range(20))
-    e=xrange(20)
+    e=range(20)

Wie Sie sehen können, wenn sie in einem for-Schleife oder Verständnis verwendet, oder wo bereits mit der Liste eingewickelt (), Bereich bleibt unverändert.

Andere Tipps

Nein, sie haben beide ihre Verwendungen:

Verwenden xrange() wenn iterieren, wie es Speicher spart. Sprich:

for x in xrange(1, one_zillion):

statt:

for x in range(1, one_zillion):

Auf der anderen Seite, verwenden Sie range(), wenn Sie tatsächlich eine Liste von Zahlen wollen.

multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven

Sie sollten range() über xrange() bevorzugen nur, wenn Sie eine aktuelle Liste benötigen. Zum Beispiel, wenn Sie die Liste von range() zurück ändern möchten, oder wenn Sie schneiden Sie es wünschen. Für Iteration oder auch nur normale Indizierung wird xrange() gut funktionieren (und in der Regel sehr viel effizienter). Es gibt einen Punkt, an dem range() ein bisschen schneller als xrange() für sehr kleine Listen, aber je nach Hardware und verschiedenen anderen Details, die Break-even in Folge der Länge sein können, 1 oder 2; nicht um etwas zu kümmern. Bevorzugen xrange().

Ein weiterer Unterschied besteht darin, dass xrange () kann keine Zahlen größer als C Ints unterstützen, so dass, wenn Sie einen Bereich mit Python des in großer Zahl Unterstützung gebaut haben wollen, müssen Sie Bereich () verwenden.

Python 2.7.3 (default, Jul 13 2012, 22:29:01) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

Python 3 nicht dieses Problem haben:

Python 3.2.3 (default, Jul 14 2012, 01:01:48) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)

xrange() ist effizienter, da stattdessen eine Liste von Objekten zu erzeugen, erzeugt es nur ein Objekt zu einer Zeit. Statt 100 ganzen Zahlen, und alle ihre Overhead und die Liste sie setzen in, die Sie gerade haben eine ganze Zahl auf einmal. Schnellere Generation, bessere Speichernutzung, effizienteren Code.

Wenn ich nicht speziell eine Liste für etwas brauchen, habe ich immer bevorzugen xrange()

range () gibt eine Liste, xrange () gibt ein xrange Objekt.

xrange () ist ein bisschen schneller und ein bisschen mehr Speicher effizient. Aber der Gewinn ist nicht sehr groß.

Der zusätzliche Speicher durch eine Liste verwendet wird, ist natürlich nicht nur verschwendet, Listen mehr Funktionalität (Scheibe, wiederholt, einfügen, ...). Genaue Unterschiede können in der Dokumentation . Es gibt keine bonehard Regel verwenden, was notwendig ist.

Python 3.0 ist noch in der Entwicklung, aber IIRC range () wird sehr ähnlich () von 2.X xrange und Liste (range ()) verwendet wird, Listen zu erzeugen.

Ich möchte nur sagen, dass es wirklich nicht so schwierig ist, ein xrange Objekt mit Scheibe und Indizierung Funktionalität zu erhalten. Ich habe einigen Code geschrieben, die ziemlich dingt gut funktioniert und ist genauso schnell wie xrange für, wenn es zählt (Iterationen).

from __future__ import division

def read_xrange(xrange_object):
    # returns the xrange object's start, stop, and step
    start = xrange_object[0]
    if len(xrange_object) > 1:
       step = xrange_object[1] - xrange_object[0]
    else:
        step = 1
    stop = xrange_object[-1] + step
    return start, stop, step

class Xrange(object):
    ''' creates an xrange-like object that supports slicing and indexing.
    ex: a = Xrange(20)
    a.index(10)
    will work

    Also a[:5]
    will return another Xrange object with the specified attributes

    Also allows for the conversion from an existing xrange object
    '''
    def __init__(self, *inputs):
        # allow inputs of xrange objects
        if len(inputs) == 1:
            test, = inputs
            if type(test) == xrange:
                self.xrange = test
                self.start, self.stop, self.step = read_xrange(test)
                return

        # or create one from start, stop, step
        self.start, self.step = 0, None
        if len(inputs) == 1:
            self.stop, = inputs
        elif len(inputs) == 2:
            self.start, self.stop = inputs
        elif len(inputs) == 3:
            self.start, self.stop, self.step = inputs
        else:
            raise ValueError(inputs)

        self.xrange = xrange(self.start, self.stop, self.step)

    def __iter__(self):
        return iter(self.xrange)

    def __getitem__(self, item):
        if type(item) is int:
            if item < 0:
                item += len(self)

            return self.xrange[item]

        if type(item) is slice:
            # get the indexes, and then convert to the number
            start, stop, step = item.start, item.stop, item.step
            start = start if start != None else 0 # convert start = None to start = 0
            if start < 0:
                start += start
            start = self[start]
            if start < 0: raise IndexError(item)
            step = (self.step if self.step != None else 1) * (step if step != None else 1)
            stop = stop if stop is not None else self.xrange[-1]
            if stop < 0:
                stop += stop

            stop = self[stop]
            stop = stop

            if stop > self.stop:
                raise IndexError
            if start < self.start:
                raise IndexError
            return Xrange(start, stop, step)

    def index(self, value):
        error = ValueError('object.index({0}): {0} not in object'.format(value))
        index = (value - self.start)/self.step
        if index % 1 != 0:
            raise error
        index = int(index)


        try:
            self.xrange[index]
        except (IndexError, TypeError):
            raise error
        return index

    def __len__(self):
        return len(self.xrange)

Ehrlich gesagt, ich glaube, das ganze Thema irgendwie albern ist und xrange sollte auf jeden Fall all dies zu tun ...

Ein gutes Beispiel in Buch gegeben: Practical Python von Magnus Lie Hetland

>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

Ich würde mit Bereich statt xrange im vorhergehenden nicht empfehlen Beispiel-obwohl nur die ersten fünf Zahlen benötigt werden, Bereich berechnet alle Zahlen, und dass eine Menge nehmen kann von Zeit. Mit xrange, ist dies kein Problem, weil es nur diese Zahlen berechnet benötigt.

Ja, ich lesen @ Brians Antwort. In Python 3, Bereich () ist ein Generator sowieso und xrange () existiert nicht

Gehen Sie mit Bereich aus diesen Gründen:

1) xrange wird in neueren Python-Versionen nicht mehr unterstützt. Dies ermöglicht Ihnen eine einfache zukünftige Kompatibilität.

2) Bereich nimmt auf der Effizienz mit xrange verbunden.

Okay, jeder hier als eine andere Meinung in Bezug auf die Vor- und Nachteile und Vorteile von xrange über die Entfernung. Sie sind meist richtig, xrange ist ein Iterator, und Bereich konkretisiert und erstellt eine aktuelle Liste. Für die Mehrheit der Fälle wird man nicht wirklich einen Unterschied zwischen den beiden bemerken. (Sie können Ihre Karte mit Bereich verwenden, aber nicht mit xrange, aber es wird mehr Speicher.)

Was ich glaube, Sie Kundgebung wollen, aber hören, ist, dass die bevorzugte Wahl xrange ist. Da Bereich in Python 3 ein Iterator ist, wird das Code-Konvertierungstool 2to3 korrekt alle Verwendungen von xrange zu Bereich umwandeln, und einen Fehler oder eine Warnung für die Verwendung von Bereich werfen. Wenn Sie Ihren Code in Zukunft leicht konvertieren sicher sein wollen, dann verwenden Sie xrange nur, und die Liste (xrange), wenn Sie sicher sind, dass Sie eine Liste wollen. Das erfuhr ich während des CPython Sprint bei PyCon in diesem Jahr (2008) in Chicago.

  • range(): range(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 range() 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__
Out[3]: xrange([start,] stop[, step]) -> xrange object

range() macht das Gleiche wie xrange() in Python 3 zu tun verwendet und es gibt nicht Begriff xrange() existiert in Python 3. range() kann tatsächlich schneller in einigem Szenario, wenn Sie über die gleiche Sequenz mehrmals iteriert. xrange() hat die Integer-Objekt jedes Mal zu rekonstruieren, aber range() werden echte Integer-Objekte haben.

Während xrange ist schneller als range in den meisten Fällen ist der Unterschied in der Leistung ziemlich minimal. Das kleine Programm unten vergleicht Iterieren über eine range und einen xrange:

import timeit
# Try various list sizes.
for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
  # Time doing a range and an xrange.
  rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
  xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
  # Print the result
  print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)

Die folgenden Ergebnisse zeigen, dass xrange ist in der Tat schneller, aber nicht genug, um zu schwitzen.

Loop list of len 1: range=0.0003, xrange=0.0003
Loop list of len 10: range=0.0013, xrange=0.0011
Loop list of len 100: range=0.0068, xrange=0.0034
Loop list of len 1000: range=0.0609, xrange=0.0438
Loop list of len 10000: range=0.5527, xrange=0.5266
Loop list of len 100000: range=10.1666, xrange=7.8481
Loop list of len 1000000: range=168.3425, xrange=155.8719

So mit allen Mitteln xrange verwenden, aber wenn Sie auf einer eingeschränkten Hardware sind, nicht zu viel Sorgen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top