#import warnings def _xrangeiter_generic_gen(value, step, len): end = value + step * len if step > 0: while value < end: yield value value += step else: while value > end: yield value value += step class _xrangeiter(object): __slots__ = ('index', 'start', 'len', 'step') def __init__(self, start, step, len): #assert len >= 0 self.start = start self.len = len self.step = step self.index = 0 def next(self): if self.index >= self.len: raise StopIteration value = self.start + self.index * self.step self.index += 1 return value def _next(self): # Alternate implementation of next() if not self.len: raise StopIteration value = self.start self.start += self.step self.len -= 1 return value def __length_hint__(self): return self.len - self.index def _get_len_of_range(lo, hi, step): if lo < hi: return ((hi - lo - 1) / step) + 1 return 0 class 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.""" __slots__ = ('start', 'end', 'step', '_len') #int_iter = _xrangeiter #int_iter = _xrangeiter_generic_gen int_iter = xrangeiter def __init__(self, start, end=None, step=None): # XXX(nnorwitz): warn and truncate if start, end, or step are floats if end is None: end = start start = 0 if step is None: step = 1 elif step == 0: raise ValueError('xrange() arg 3 must not be zero') self.step = step self.start = start self.end = end self._len = 0 if step > 0: self._len = _get_len_of_range(start, end, step) else: self._len = _get_len_of_range(end, start, -step) def _is_int(self): return type(self.start) is type(self.end) is type(self.step) is int def _make_iter(self, start, step, len): if self._is_int(): return self.int_iter(start, step, len) return _xrangeiter(start, step, len) def __reversed__(self): new_start = self.start + (self._len - 1) * self.step return self._make_iter(new_start, -self.step, self._len) def __iter__(self): return self._make_iter(self.start, self.step, self._len) def __getitem__(self, item): if isinstance(item, slice): # XXX(nnorwitz): handle slices raise ValueError("Can't handle slices yet") return self.start + (item % self._len) * self.step def __repr__(self): max_value = self.start + (self._len * self.step) if self.step == 1 and self.start == 0: return 'xrange(%d)' % max_value if self.step == 1: return 'xrange(%d, %d)' % (self.start, max_value) return 'xrange(%d, %d, %d)' % (self.start, max_value, self.step) def __len__(self): return self._len