1 #!/usr/bin/env python 2 3 """ 4 Span-related objects. 5 6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from __builtins__.sequence import _max, _min 23 24 class xrange: 25 26 "Implementation of xrange." 27 28 NO_END = object() 29 30 def __init__(self, start_or_end, end=NO_END, step=1): 31 32 "Initialise the xrange with the given 'start_or_end', 'end' and 'step'." 33 34 if end is xrange.NO_END: 35 self.start = 0 36 self.end = start_or_end 37 else: 38 self.start = start_or_end 39 self.end = end 40 41 self.step = step 42 43 # Constrain the end according to the start and step. 44 45 if step > 0: 46 self.end = _max(self.start, self.end) 47 elif step < 0: 48 self.end = _min(self.start, self.end) 49 else: 50 raise ValueError(self.step) 51 52 self.current = self.start 53 54 def __str__(self): 55 56 "Return a string representation." 57 58 b = buffer([self.__name__, "(", self.start, ", ", self.end, ", ", self.step, ")"]) 59 return str(b) 60 61 __repr__ = __str__ 62 63 def __len__(self): 64 65 "Return the length of the range." 66 67 return (self.end - self.start) / self.step 68 69 def __iter__(self): 70 71 "Return an iterator, currently self." 72 73 return self 74 75 def next(self): 76 77 "Return the next item or raise a StopIteration exception." 78 79 if self.step < 0 and self.current <= self.end or self.step > 0 and self.current >= self.end: 80 raise StopIteration() 81 82 current = self.current 83 self.current += self.step 84 return current 85 86 class slice(xrange): 87 88 "Implementation of slice." 89 90 def __init__(self, start_or_end=None, end=xrange.NO_END, step=1): 91 92 "Initialise the slice with the given 'start_or_end', 'end' and 'step'." 93 94 get_using(xrange.__init__, self)(start_or_end, end, step) 95 96 def range(start_or_end, end=None, step=1): 97 98 "Implementation of range." 99 100 return list(xrange(start_or_end, end, step)) 101 102 # vim: tabstop=4 expandtab shiftwidth=4