463 Stimmen

Sollten Sie immer xrange() gegenüber range() bevorzugen?

Warum oder warum nicht?

8voto

jschultz Punkte 146

Range() gibt eine Liste zurück, xrange() gibt ein xrange-Objekt zurück.

xrange() ist etwas schneller und etwas speichereffizienter. Aber der Gewinn ist nicht sehr groß.

Der zusätzliche Speicherplatz, den eine Liste verbraucht, ist natürlich nicht nur vergeudet, sondern Listen haben mehr Funktionen (Slice, Repeat, Insert, ...). Die genauen Unterschiede finden Sie in der Dokumentation . Es gibt keine feste Regel, verwenden Sie, was benötigt wird.

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

5voto

Garrett Berg Punkte 2515

Ich möchte nur sagen, dass es WIRKLICH nicht so schwierig ist, ein xrange-Objekt mit Slice- und Indexierungsfunktionalität zu erhalten. Ich habe einige Code geschrieben, die ziemlich verdammt 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, finde ich das ganze Thema ziemlich albern, und xrange sollte das alles sowieso machen...

4voto

torial Punkte 13003

Aus diesen Gründen sollten Sie sich für die Reichweite entscheiden:

1) xrange wird in neueren Python-Versionen verschwinden. Dies gibt Ihnen eine einfache zukünftige Kompatibilität.

2) range übernimmt die mit xrange verbundenen Effizienzen.

4voto

Grijesh Chauhan Punkte 54909

Ein gutes Beispiel aus dem Buch: Praktisches Python Von Magnus Lie Hetland

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

Ich würde nicht empfehlen, range anstelle von xrange im vorangegangenen Beispiel zu verwenden - auch wenn nur die ersten fünf Zahlen benötigt werden, berechnet range alle Zahlen, und das kann sehr viel viel Zeit in Anspruch. Mit xrange ist dies kein Problem, da nur die benötigten Zahlen berechnet werden.

Ja, ich habe die Antwort von @Brian gelesen: In Python 3 ist range() sowieso ein Generator und xrange() gibt es nicht.

3voto

speedplane Punkte 14917

Während xrange ist schneller als range In den meisten Fällen ist der Unterschied in der Leistung ziemlich minimal. Das folgende kleine Programm vergleicht die Iteration über eine range und ein 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 nachstehenden Ergebnisse zeigen, dass xrange ist in der Tat schneller, aber nicht genug, um darüber 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

Verwenden Sie also auf jeden Fall xrange aber wenn Sie nicht gerade auf einer eingeschränkten Hardware arbeiten, sollten Sie sich nicht zu viele Gedanken darüber machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X