@@ -26,13 +26,21 @@ class xrange(object):
2626 True
2727 >>> list(xrange(0, 7, 2)) == list(range(0, 7, 2))
2828 True
29+ >>> list(xrange(8, 0, -2)) == list(range(8, 0, -2))
30+ True
2931 >>> foobar = xrange(1, 10)
3032 >>> 7 in foobar
3133 True
3234 >>> 11 in foobar
3335 False
3436 >>> foobar[0]
3537 1
38+ >>> 6 in xrange(8, 0, -2)
39+ True
40+ >>> 0 in xrange(8, 0, -2)
41+ False
42+ >>> xrange(0, 10, 2).index(4)
43+ 2
3644 """
3745
3846 __slots__ = ['_slice' ]
@@ -71,10 +79,17 @@ def __len__(self):
7179 return self ._len ()
7280
7381 def _len (self ):
74- return max (0 , 1 + int ((self .stop - 1 - self .start ) // self .step ))
82+ if self .step > 0 :
83+ lo , hi , step = self .start , self .stop , self .step
84+ else : # Note: normalizing for descending ranges (negative step)
85+ lo , hi , step = self .stop , self .start , - self .step
86+ return max (0 , (hi - lo + step - 1 ) // step )
7587
7688 def __contains__ (self , value ):
77- return (self .start <= value < self .stop ) and (value - self .start ) % self .step == 0
89+ if self .step > 0 :
90+ return self .start <= value < self .stop and (value - self .start ) % self .step == 0
91+ else :
92+ return self .stop < value <= self .start and (value - self .start ) % self .step == 0
7893
7994 def __getitem__ (self , index ):
8095 if isinstance (index , slice ):
@@ -98,7 +113,7 @@ def _index(self, i):
98113 return self .start + self .step * i
99114
100115 def index (self , i ):
101- if self . start <= i < self . stop :
102- return i - self .start
116+ if i in self :
117+ return ( i - self .start ) // self . step # Note: also accounts for step != 1 (and descending ranges)
103118 else :
104119 raise ValueError ("%d is not in list" % i )
0 commit comments