# Example of a generator: re-implement the built-in range function # without actually constructing the list of values. (It turns out # that the built-in function is about 20 times faster -- that's why # it's built-in. :-) # Wrapper function to emulate the complicated range() arguments def range(*a): if len(a) == 1: start, stop, step = 0, a[0], 1 elif len(a) == 2: start, stop = a step = 1 elif len(a) == 3: start, stop, step = a else: raise TypeError, 'range() needs 1-3 arguments' return Range(start, stop, step) # Class implementing a range object. # To the user the instances feel like immutable sequences # (and you can't concatenate or slice them) class Range: # initialization -- should be called only by range() above def __init__(self, start, stop, step): if step == 0: raise ValueError, 'range() called with zero step' self.start = start self.stop = stop self.step = step self.len = max(0, int((self.stop - self.start) / self.step)) # implement `x` and is also used by print x def __repr__(self): return 'range' + `self.start, self.stop, self.step` # implement len(x) def __len__(self): return self.len # implement x[i] def __getitem__(self, i): if 0 <= i < self.len: return self.start + self.step * i else: raise IndexError, 'range[i] index out of range' # Small test program def test(): import time, __builtin__ print range(10), range(-10, 10), range(0, 10, 2) for i in range(100, -100, -10): print i, print t1 = time.time() for i in range(1000): pass t2 = time.time() for i in __builtin__.range(1000): pass t3 = time.time() print t2-t1, 'sec (class)' print t3-t2, 'sec (built-in)' test()