好的,这是更全面的实现。
class MyXRange(object): def __init__(self, a1, a2=None, step=1): if step == 0: raise ValueError("arg 3 must not be 0") if a2 is None: a1, a2 = 0, a1 if (a2 - a1) % step != 0: a2 += step - (a2 - a1) % step if cmp(a1, a2) != cmp(0, step): a2 = a1 self.start, self.stop, self.step = a1, a2, step def __iter__(self): n = self.start while cmp(n, self.stop) == cmp(0, self.step): yield n n += self.step def __repr__(self): return "MyXRange(%d,%d,%d)" % (self.start, self.stop, self.step) # NB: len(self) will convert this to an int, and may fail def __len__(self): return (self.stop - self.start)//(self.step) def __getitem__(self, key): if key < 0: key = self.__len__() + key if key < 0: raise IndexError("list index out of range") return self[key] n = self.start + self.step*key if cmp(n, self.stop) != cmp(0, self.step): raise IndexError("list index out of range") return n def __reversed__(self): return MyXRange(self.stop-self.step, self.start-self.step, -self.step) def __contains__(self, val): if val == self.start: return cmp(0, self.step) == cmp(self.start, self.stop) if cmp(self.start, val) != cmp(0, self.step): return False if cmp(val, self.stop) != cmp(0, self.step): return False return (val - self.start) % self.step == 0和一些测试:
def testMyXRange(testsize=10): def normexcept(f,args): try: r = [f(args)] except Exception, e: r = type(e) return r for i in range(-testsize,testsize+1): for j in range(-testsize,testsize+1): print i, j for k in range(-9, 10, 2): r, mr = range(i,j,k), MyXRange(i,j,k) if r != list(mr): print "iter fail: %d, %d, %d" % (i,j,k) if list(reversed(r)) != list(reversed(mr)): print "reversed fail: %d, %d, %d" % (i,j,k) if len(r) != len(mr): print "len fail: %d, %d, %d" % (i,j,k) z = [m for m in range(-testsize*2,testsize*2+1)if (m in r) != (m in mr)] if z != []: print "contains fail: %d, %d, %d, %s" % (i,j,k,(z+["..."])[:10]) z = [m for m in range(-testsize*2, testsize*2+1) if normexcept(r.__getitem__, m) != normexcept(mr.__getitem__, m)] if z != []: print "getitem fail: %d, %d, %d, %s" % (i,j,k,(z+["..."])[:10])



