19
19
"""
20
20
21
21
from collections import Sequence , Iterator
22
+ from itertools import islice
22
23
23
24
24
25
class newrange (Sequence ):
@@ -55,6 +56,18 @@ def __init__(self, *args):
55
56
self ._step = step
56
57
self ._len = (stop - start ) // step + bool ((stop - start ) % step )
57
58
59
+ @property
60
+ def start (self ):
61
+ return self ._start
62
+
63
+ @property
64
+ def stop (self ):
65
+ return self ._stop
66
+
67
+ @property
68
+ def step (self ):
69
+ return self ._step
70
+
58
71
def __repr__ (self ):
59
72
if self ._step == 1 :
60
73
return 'range(%d, %d)' % (self ._start , self ._stop )
@@ -94,12 +107,7 @@ def __contains__(self, value):
94
107
return False
95
108
96
109
def __reversed__ (self ):
97
- """Return a range which represents a sequence whose
98
- contents are the same as the sequence this range
99
- represents, but in the opposite order."""
100
- sign = self ._step / abs (self ._step )
101
- last = self ._start + ((self ._len - 1 ) * self ._step )
102
- return newrange (last , self ._start - sign , - 1 * self ._step )
110
+ return iter (self [::- 1 ])
103
111
104
112
def __getitem__ (self , index ):
105
113
"""Return the element at position ``index`` in the sequence
@@ -119,40 +127,34 @@ def __getitem_slice(self, slce):
119
127
of the sequence represented by this range.
120
128
"""
121
129
start , stop , step = slce .indices (self ._len )
122
- return newrange (self [start ], stop + self ._start , step * self ._step )
130
+ return newrange (self ._start + self ._step * start ,
131
+ self ._start + stop ,
132
+ self ._step * step )
123
133
124
134
def __iter__ (self ):
125
135
"""Return an iterator which enumerates the elements of the
126
136
sequence this range represents."""
127
- return rangeiterator (self )
137
+ return range_iterator (self )
128
138
129
139
130
- class rangeiterator (Iterator ):
140
+ class range_iterator (Iterator ):
131
141
"""An iterator for a :class:`range`.
132
142
"""
133
-
134
- def __init__ (self , rangeobj ):
135
- self ._range = rangeobj
136
-
137
- # Intialize the "last outputted value" to the value
138
- # just before the first value; this simplifies next()
139
- self ._last = self ._range ._start - self ._range ._step
140
- self ._count = 0
143
+ def __init__ (self , range_ ):
144
+ self ._stepper = islice (_count (range_ .start , range_ .step ), len (range_ ))
141
145
142
146
def __iter__ (self ):
143
- """An iterator is already an iterator, so return ``self``.
144
- """
145
147
return self
146
148
147
149
def next (self ):
148
- """Return the next element in the sequence represented
149
- by the range we are iterating, or raise StopIteration
150
- if we have passed the end of the sequence."""
151
- self . _last += self . _range . _step
152
- self . _count += 1
153
- if self . _count > self . _range . _len :
154
- raise StopIteration ()
155
- return self . _last
150
+ return next ( self . _stepper )
151
+
152
+
153
+ # itertools.count in Py 2.6 doesn't accept a step parameter
154
+ def _count ( start = 0 , step = 1 ):
155
+ while True :
156
+ yield start
157
+ start += step
156
158
157
159
158
160
__all__ = ['newrange' ]
0 commit comments