Warum oder warum nicht?
Antworten
Zu viele Anzeigen?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.
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...
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.
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.