blob: 947697a84c446f05fdba0da1f7ec843a01005e67 [file] [log] [blame]
Tim Peters6ba5f792001-06-23 20:45:43 +00001tutorial_tests = """
Tim Peters1def3512001-06-23 20:27:04 +00002Let's try a simple generator:
3
4 >>> def f():
5 ... yield 1
6 ... yield 2
7
8 >>> g = f()
9 >>> g.next()
10 1
11 >>> g.next()
12 2
13 >>> g.next()
14 Traceback (most recent call last):
15 File "<stdin>", line 1, in ?
16 File "<stdin>", line 2, in g
17 StopIteration
18
19"return" stops the generator:
20
21 >>> def f():
22 ... yield 1
23 ... return
24 ... yield 2 # never reached
25 ...
26 >>> g = f()
27 >>> g.next()
28 1
29 >>> g.next()
30 Traceback (most recent call last):
31 File "<stdin>", line 1, in ?
32 File "<stdin>", line 3, in f
33 StopIteration
34 >>> g.next() # once stopped, can't be resumed
35 Traceback (most recent call last):
36 File "<stdin>", line 1, in ?
37 StopIteration
38
39"raise StopIteration" stops the generator too:
40
41 >>> def f():
42 ... yield 1
43 ... return
44 ... yield 2 # never reached
45 ...
46 >>> g = f()
47 >>> g.next()
48 1
49 >>> g.next()
50 Traceback (most recent call last):
51 File "<stdin>", line 1, in ?
52 StopIteration
53 >>> g.next()
54 Traceback (most recent call last):
55 File "<stdin>", line 1, in ?
56 StopIteration
57
58However, they are not exactly equivalent:
59
60 >>> def g1():
61 ... try:
62 ... return
63 ... except:
64 ... yield 1
65 ...
66 >>> list(g1())
67 []
68
69 >>> def g2():
70 ... try:
71 ... raise StopIteration
72 ... except:
73 ... yield 42
74 >>> print list(g2())
75 [42]
76
77This may be surprising at first:
78
79 >>> def g3():
80 ... try:
81 ... return
82 ... finally:
83 ... yield 1
84 ...
85 >>> list(g3())
86 [1]
87
88Let's create an alternate range() function implemented as a generator:
89
90 >>> def yrange(n):
91 ... for i in range(n):
92 ... yield i
93 ...
94 >>> list(yrange(5))
95 [0, 1, 2, 3, 4]
96
97Generators always return to the most recent caller:
98
99 >>> def creator():
100 ... r = yrange(5)
101 ... print "creator", r.next()
102 ... return r
103 ...
104 >>> def caller():
105 ... r = creator()
106 ... for i in r:
107 ... print "caller", i
108 ...
109 >>> caller()
110 creator 0
111 caller 1
112 caller 2
113 caller 3
114 caller 4
115
116Generators can call other generators:
117
118 >>> def zrange(n):
119 ... for i in yrange(n):
120 ... yield i
121 ...
122 >>> list(zrange(5))
123 [0, 1, 2, 3, 4]
124
125"""
126
Tim Peters6ba5f792001-06-23 20:45:43 +0000127# The examples from PEP 255.
128
129pep_tests = """
130
131Specification: Return
132
133 Note that return isn't always equivalent to raising StopIteration: the
134 difference lies in how enclosing try/except constructs are treated.
135 For example,
136
137 >>> def f1():
138 ... try:
139 ... return
140 ... except:
141 ... yield 1
142 >>> print list(f1())
143 []
144
145 because, as in any function, return simply exits, but
146
147 >>> def f2():
148 ... try:
149 ... raise StopIteration
150 ... except:
151 ... yield 42
152 >>> print list(f2())
153 [42]
154
155 because StopIteration is captured by a bare "except", as is any
156 exception.
157
158Specification: Generators and Exception Propagation
159
160 >>> def f():
161 ... return 1/0
162 >>> def g():
163 ... yield f() # the zero division exception propagates
164 ... yield 42 # and we'll never get here
165 >>> k = g()
166 >>> k.next()
167 Traceback (most recent call last):
168 File "<stdin>", line 1, in ?
169 File "<stdin>", line 2, in g
170 File "<stdin>", line 2, in f
171 ZeroDivisionError: integer division or modulo by zero
172 >>> k.next() # and the generator cannot be resumed
173 Traceback (most recent call last):
174 File "<stdin>", line 1, in ?
175 StopIteration
176 >>>
177
178Specification: Try/Except/Finally
179
180 >>> def f():
181 ... try:
182 ... yield 1
183 ... try:
184 ... yield 2
185 ... 1/0
186 ... yield 3 # never get here
187 ... except ZeroDivisionError:
188 ... yield 4
189 ... yield 5
190 ... raise
191 ... except:
192 ... yield 6
193 ... yield 7 # the "raise" above stops this
194 ... except:
195 ... yield 8
196 ... yield 9
197 ... try:
198 ... x = 12
199 ... finally:
200 ... yield 10
201 ... yield 11
202 >>> print list(f())
203 [1, 2, 4, 5, 8, 9, 10, 11]
204 >>>
205
206
207Guido's binary tree example.
208
209 >>> # A binary tree class.
210 >>> class Tree:
211 ...
212 ... def __init__(self, label, left=None, right=None):
213 ... self.label = label
214 ... self.left = left
215 ... self.right = right
216 ...
217 ... def __repr__(self, level=0, indent=" "):
218 ... s = level*indent + `self.label`
219 ... if self.left:
220 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
221 ... if self.right:
222 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
223 ... return s
224 ...
225 ... def __iter__(self):
226 ... return inorder(self)
227
228 >>> # Create a Tree from a list.
229 >>> def tree(list):
230 ... n = len(list)
231 ... if n == 0:
232 ... return []
233 ... i = n / 2
234 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
235
236 >>> # Show it off: create a tree.
237 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
238
239 >>> # A recursive generator that generates Tree leaves in in-order.
240 >>> def inorder(t):
241 ... if t:
242 ... for x in inorder(t.left):
243 ... yield x
244 ... yield t.label
245 ... for x in inorder(t.right):
246 ... yield x
247
248 >>> # Show it off: create a tree.
249 ... t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
250 ... # Print the nodes of the tree in in-order.
251 ... for x in t:
252 ... print x,
253 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
254
255 >>> # A non-recursive generator.
256 >>> def inorder(node):
257 ... stack = []
258 ... while node:
259 ... while node.left:
260 ... stack.append(node)
261 ... node = node.left
262 ... yield node.label
263 ... while not node.right:
264 ... try:
265 ... node = stack.pop()
266 ... except IndexError:
267 ... return
268 ... yield node.label
269 ... node = node.right
270
271 >>> # Exercise the non-recursive generator.
272 >>> for x in t:
273 ... print x,
274 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
275
276"""
277
278# A few examples from Iterator-List and Python-Dev email.
279
280email_tests = """
281
282The difference between yielding None and returning it.
283
284>>> def g():
285... for i in range(3):
286... yield None
287... yield None
288... return
289>>> list(g())
290[None, None, None, None]
291
292Ensure that explicitly raising StopIteration acts like any other exception
293in try/except, not like a return.
294
295>>> def g():
296... yield 1
297... try:
298... raise StopIteration
299... except:
300... yield 2
301... yield 3
302>>> list(g())
303[1, 2, 3]
304"""
305
Tim Peters0f9da0a2001-06-23 21:01:47 +0000306# Fun tests (for sufficiently warped notions of "fun").
307
308fun_tests = """
309
310Build up to a recursive Sieve of Eratosthenes generator.
311
312>>> def firstn(g, n):
313... return [g.next() for i in range(n)]
314
315>>> def intsfrom(i):
316... while 1:
317... yield i
318... i += 1
319
320>>> firstn(intsfrom(5), 7)
321[5, 6, 7, 8, 9, 10, 11]
322
323>>> def exclude_multiples(n, ints):
324... for i in ints:
325... if i % n:
326... yield i
327
328>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
329[1, 2, 4, 5, 7, 8]
330
331>>> def sieve(ints):
332... prime = ints.next()
333... yield prime
334... not_divisible_by_prime = exclude_multiples(prime, ints)
335... for p in sieve(not_divisible_by_prime):
336... yield p
337
338>>> primes = sieve(intsfrom(2))
339>>> firstn(primes, 20)
340[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
341"""
342
Tim Peters6ba5f792001-06-23 20:45:43 +0000343__test__ = {"tut": tutorial_tests,
344 "pep": pep_tests,
Tim Peters0f9da0a2001-06-23 21:01:47 +0000345 "email": email_tests,
346 "fun": fun_tests}
Tim Peters1def3512001-06-23 20:27:04 +0000347
348# Magic test name that regrtest.py invokes *after* importing this module.
349# This worms around a bootstrap problem.
350# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
351# so this works as expected in both ways of running regrtest.
352def test_main():
353 import doctest, test_generators
354 doctest.testmod(test_generators)
355
356# This part isn't needed for regrtest, but for running the test directly.
357if __name__ == "__main__":
358 test_main()