The built-in xrange is fast, but it does not support floats and longs as start,stop,step parameters. This means you cannot iterate large number (that don't fit in an int) ranges via xrange as you would with small numbers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | class xrange(object):
"""A pure-python implementation of xrange.
Can handle float/long start/stop/step arguments and slice indexing"""
__slots__ = ['_slice']
def __init__(self, *args):
self._slice = slice(*args)
if self._slice.stop is None:
# slice(*args) will never put None in stop unless it was
# given as None explicitly.
raise TypeError("xrange stop must not be None")
@property
def start(self):
if self._slice.start is not None:
return self._slice.start
return 0
@property
def stop(self):
return self._slice.stop
@property
def step(self):
if self._slice.step is not None:
return self._slice.step
return 1
def __hash__(self):
return hash(self._slice)
def __cmp__(self, other):
return (cmp(type(self), type(other)) or
cmp(self._slice, other._slice))
def __repr__(self):
return '%s(%r, %r, %r)' % (self.__class__.__name__,
self.start, self.stop, self.step)
def __len__(self):
return self._len()
def _len(self):
return max(0, int((self.stop - self.start) / self.step))
def __getitem__(self, index):
if isinstance(index, slice):
start, stop, step = index.indices(self._len())
return xrange(self._index(start),
self._index(stop), step*self.step)
elif isinstance(index, (int, long)):
if index < 0:
fixed_index = index + self._len()
else:
fixed_index = index
if not 0 <= fixed_index < self._len():
raise IndexError("Index %d out of %r" % (index, self))
return self._index(fixed_index)
else:
raise TypeError("xrange indices must be slices or integers")
def _index(self, i):
return self.start + self.step * i
|
Example use:
>>> for i in xrange(10000000000000000, 10000000000000005):
... print i
>>> for i in xrange(3, 5, 0.2):
... print i
>>> xrange(0, 10, 2)[:3]
These use-cases are not supported by the built-in xrange.
Tags: algorithms
a bug, I thnk. for i in xrange(1000000000000000000000, 1000000000000000000005, 2): print i,
produces 1000000000000000000000 1000000000000000000002
instead of the expected 1000000000000000000000 1000000000000000000002 1000000000000000000004
AND
for i in xrange(3, 4.1, 0.2): print i,
produces 3.0 3.2 3.4 3.6 3.8 instead of the expected 3.0 3.2 3.4 3.6 3.8 4.0
Maybe it is not a bug. In fact it may be a rounding problem. Take the xrange(3,4.1,0.2) example: there should be 6 items: 3.0, 3.2, 3.4, 3.6, 3.8 and 4.0, but when the code is calculating _len: (4.1-3)/0.2 is 5.5, and int(5.5)=5.