source: python/vendor/Python-2.7.6/Demo/classes/Range.py

Last change on this file was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 3.1 KB
Line 
1"""Example of a generator: re-implement the built-in range function
2without actually constructing the list of values.
3
4OldStyleRange is coded in the way required to work in a 'for' loop before
5iterators were introduced into the language; using __getitem__ and __len__ .
6
7"""
8def handleargs(arglist):
9 """Take list of arguments and extract/create proper start, stop, and step
10 values and return in a tuple"""
11 try:
12 if len(arglist) == 1:
13 return 0, int(arglist[0]), 1
14 elif len(arglist) == 2:
15 return int(arglist[0]), int(arglist[1]), 1
16 elif len(arglist) == 3:
17 if arglist[2] == 0:
18 raise ValueError("step argument must not be zero")
19 return tuple(int(x) for x in arglist)
20 else:
21 raise TypeError("range() accepts 1-3 arguments, given", len(arglist))
22 except TypeError:
23 raise TypeError("range() arguments must be numbers or strings "
24 "representing numbers")
25
26def genrange(*a):
27 """Function to implement 'range' as a generator"""
28 start, stop, step = handleargs(a)
29 value = start
30 while value < stop:
31 yield value
32 value += step
33
34class oldrange:
35 """Class implementing a range object.
36 To the user the instances feel like immutable sequences
37 (and you can't concatenate or slice them)
38
39 Done using the old way (pre-iterators; __len__ and __getitem__) to have an
40 object be used by a 'for' loop.
41
42 """
43
44 def __init__(self, *a):
45 """ Initialize start, stop, and step values along with calculating the
46 nubmer of values (what __len__ will return) in the range"""
47 self.start, self.stop, self.step = handleargs(a)
48 self.len = max(0, (self.stop - self.start) // self.step)
49
50 def __repr__(self):
51 """implement repr(x) which is also used by print"""
52 return 'range(%r, %r, %r)' % (self.start, self.stop, self.step)
53
54 def __len__(self):
55 """implement len(x)"""
56 return self.len
57
58 def __getitem__(self, i):
59 """implement x[i]"""
60 if 0 <= i <= self.len:
61 return self.start + self.step * i
62 else:
63 raise IndexError, 'range[i] index out of range'
64
65
66def test():
67 import time, __builtin__
68 #Just a quick sanity check
69 correct_result = __builtin__.range(5, 100, 3)
70 oldrange_result = list(oldrange(5, 100, 3))
71 genrange_result = list(genrange(5, 100, 3))
72 if genrange_result != correct_result or oldrange_result != correct_result:
73 raise Exception("error in implementation:\ncorrect = %s"
74 "\nold-style = %s\ngenerator = %s" %
75 (correct_result, oldrange_result, genrange_result))
76 print "Timings for range(1000):"
77 t1 = time.time()
78 for i in oldrange(1000):
79 pass
80 t2 = time.time()
81 for i in genrange(1000):
82 pass
83 t3 = time.time()
84 for i in __builtin__.range(1000):
85 pass
86 t4 = time.time()
87 print t2-t1, 'sec (old-style class)'
88 print t3-t2, 'sec (generator)'
89 print t4-t3, 'sec (built-in)'
90
91
92if __name__ == '__main__':
93 test()
Note: See TracBrowser for help on using the repository browser.