44import collections
55
66from python_toolbox import math_tools
7- from python_toolbox import cute_iter_tools
87
98infinity = float ('inf' )
109infinities = (infinity , - infinity )
1312class CanonicalSlice (object ):
1413 def __init__ (self , slice_ , iterable_or_length = None , offset = 0 ):
1514 '''
16- Parse a `slice` object into a `CanonicalSlice` with start, stop, step.
15+ A canonical representation of a `slice` with ` start`, ` stop`, and ` step` .
1716
1817 This is helpful because `slice`'s own `.start`, `.stop` and `.step` are
19- sometimes specified as `None` for convenience, so Python will infer
20- them automatically. Here we make them explicit. If we're given an
21- iterable (or the length of one) in `iterable_or_length`, we'll give a
22- canoncial slice for that length, otherwise we'll do a generic one,
23- which is rarely usable for actual slicing because it often has
24- `infinity` in it, so it's useful only for canonalization. (e.g.
25- checking whether two different slices are actually equal.)
18+ sometimes specified as `None` for convenience, so Python will infer them
19+ automatically. Here we make them explicit. If we're given an iterable (or
20+ the length of one) in `iterable_or_length`, we'll give a canoncial slice
21+ for that length, otherwise we'll do a generic one, which is rarely usable
22+ for actual slicing because it often has `infinity` in it, so it's useful
23+ only for canonalization. (e.g. checking whether two different slices are
24+ actually equal.)
2625
2726 When doing a generic canonical slice (without giving an iterable or
2827 length):
29- If `start` is `None`, it will be set to `0` (if the `step` is
30- positive) or `infinity` (if the `step` is negative.)
31- If `stop` is `None`, it will be set to `infinity` (if the `step` is
28+
29+ - If `start` is `None`, it will be set to `0` (if the `step` is positive)
30+ or `infinity` (if the `step` is negative.)
31+
32+ - If `stop` is `None`, it will be set to `infinity` (if the `step` is
3233 positive) or `0` (if the `step` is negative.)
33- If `step` is `None`, it will be changed to the default `1`.
34+
35+ - If `step` is `None`, it will be changed to the default `1`.
36+
3437 '''
38+
39+ def __init__ (self , slice_ , iterable_or_length = None , offset = 0 ):
3540 from python_toolbox import sequence_tools
41+ from python_toolbox import cute_iter_tools
3642
3743 if isinstance (slice_ , CanonicalSlice ):
3844 slice_ = slice (slice_ .start , slice_ .stop , slice_ .step )
@@ -46,7 +52,7 @@ def __init__(self, slice_, iterable_or_length=None, offset=0):
4652 self .length = sequence_tools .get_length (iterable_or_length )
4753 else :
4854 assert isinstance (iterable_or_length , collections .Iterable )
49- self .length = cute_iter_tools .get_length (iterable )
55+ self .length = cute_iter_tools .get_length (iterable_or_length )
5056 else :
5157 self .length = None
5258
@@ -105,7 +111,7 @@ def __init__(self, slice_, iterable_or_length=None, offset=0):
105111 # #
106112 ### Finished parsing `stop`. ##########################################
107113
108- if (self .step > 0 and self .start >= self .stop > 0 ) or \
114+ if (self .step > 0 and self .start >= self .stop >= 0 ) or \
109115 (self .step < 0 and self .stop >= self .start ):
110116 # We have a case of an empty slice.
111117 self .start = self .stop = 0
0 commit comments