Lichen

lib/__builtins__/span.py

794:7dd8e4815848
2017-03-31 Paul Boddie Introduced a multiple outcome result which can be used to provide a choice of return values to supply the initialiser and alias details.
     1 #!/usr/bin/env python     2      3 """     4 Span-related objects.     5      6 Copyright (C) 2015, 2016, 2017 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 class slice:    23     24     "Implementation of slice."    25     26     NO_END = object()    27     28     def __init__(self, start_or_end=None, end=NO_END, step=1):    29     30         "Initialise the slice with the given 'start_or_end', 'end' and 'step'."    31     32         if end is slice.NO_END:    33             self.start = 0    34             self.end = start_or_end    35         else:    36             self.start = start_or_end    37             self.end = end    38     39         if step == 0:    40             raise ValueError(self.step)    41     42         self.step = step    43     44     def __str__(self):    45     46         "Return a string representation."    47     48         b = buffer([self.__parent__.__name__, ".", self.__name__, "(", self.start, ", ", self.end, ", ", self.step, ")"])    49         return str(b)    50     51     __repr__ = __str__    52     53 class xrange(slice):    54     55     "Implementation of xrange."    56     57     def __init__(self, start_or_end, end=slice.NO_END, step=1):    58     59         "Initialise the xrange with the given 'start_or_end', 'end' and 'step'."    60     61         get_using(slice.__init__, self)(start_or_end, end, step)    62     63         # Constrain the end according to the start and step.    64     65         if step > 0:    66             self.end = _max(self.start, self.end)    67         elif step < 0:    68             self.end = _min(self.start, self.end)    69         else:    70             raise ValueError(self.step)    71     72     def __len__(self):    73     74         "Return the length of the range."    75     76         n = (self.end - self.start) / self.step    77         last = self.start + (n * self.step)    78         if last == self.end:    79             return n    80         else:    81             return n + 1    82     83     def __iter__(self):    84     85         "Return an iterator, currently self."    86     87         return xrangeiterator(self.start, self.step, self.__len__())    88     89 class xrangeiterator:    90     91     "An iterator over an xrange."    92     93     def __init__(self, start, step, count):    94     95         "Initialise the iterator with the given 'obj'."    96     97         self.current = start    98         self.step = step    99         self.count = count   100    101     def next(self):   102    103         "Return the next item or raise a StopIteration exception."   104    105         if not self.count:   106             raise StopIteration   107    108         current = self.current   109         self.current = self.current.__add__(self.step)   110         self.count = self.count.__sub__(1)   111         return current   112    113 def range(start_or_end, end=None, step=1):   114    115     "Implementation of range."   116    117     return list(xrange(start_or_end, end, step))   118    119 def _max(x, y):   120    121     "Return the maximum of 'x' and 'y'."   122    123     if x >= y:   124         return x   125     else:   126         return y   127    128 def _min(x, y):   129    130     "Return the minimum of 'x' and 'y'."   131    132     if x <= y:   133         return x   134     else:   135         return y   136    137 # vim: tabstop=4 expandtab shiftwidth=4