blob: 3dd468b1cc2788b1eb64232c835ac36affc967f7 [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
Tim Petersb9e9ff12001-06-24 03:44:52 +00008 >>> for i in f():
9 ... print i
10 1
11 2
Tim Peters1def3512001-06-23 20:27:04 +000012 >>> g = f()
13 >>> g.next()
14 1
15 >>> g.next()
16 2
Tim Petersea2e97a2001-06-24 07:10:02 +000017
Tim Peters2106ef02001-06-25 01:30:12 +000018"Falling off the end" stops the generator:
Tim Petersea2e97a2001-06-24 07:10:02 +000019
Tim Peters1def3512001-06-23 20:27:04 +000020 >>> g.next()
21 Traceback (most recent call last):
22 File "<stdin>", line 1, in ?
23 File "<stdin>", line 2, in g
24 StopIteration
25
Tim Petersea2e97a2001-06-24 07:10:02 +000026"return" also stops the generator:
Tim Peters1def3512001-06-23 20:27:04 +000027
28 >>> def f():
29 ... yield 1
30 ... return
31 ... yield 2 # never reached
32 ...
33 >>> g = f()
34 >>> g.next()
35 1
36 >>> g.next()
37 Traceback (most recent call last):
38 File "<stdin>", line 1, in ?
39 File "<stdin>", line 3, in f
40 StopIteration
41 >>> g.next() # once stopped, can't be resumed
42 Traceback (most recent call last):
43 File "<stdin>", line 1, in ?
44 StopIteration
45
46"raise StopIteration" stops the generator too:
47
48 >>> def f():
49 ... yield 1
50 ... return
51 ... yield 2 # never reached
52 ...
53 >>> g = f()
54 >>> g.next()
55 1
56 >>> g.next()
57 Traceback (most recent call last):
58 File "<stdin>", line 1, in ?
59 StopIteration
60 >>> g.next()
61 Traceback (most recent call last):
62 File "<stdin>", line 1, in ?
63 StopIteration
64
65However, they are not exactly equivalent:
66
67 >>> def g1():
68 ... try:
69 ... return
70 ... except:
71 ... yield 1
72 ...
73 >>> list(g1())
74 []
75
76 >>> def g2():
77 ... try:
78 ... raise StopIteration
79 ... except:
80 ... yield 42
81 >>> print list(g2())
82 [42]
83
84This may be surprising at first:
85
86 >>> def g3():
87 ... try:
88 ... return
89 ... finally:
90 ... yield 1
91 ...
92 >>> list(g3())
93 [1]
94
95Let's create an alternate range() function implemented as a generator:
96
97 >>> def yrange(n):
98 ... for i in range(n):
99 ... yield i
100 ...
101 >>> list(yrange(5))
102 [0, 1, 2, 3, 4]
103
104Generators always return to the most recent caller:
105
106 >>> def creator():
107 ... r = yrange(5)
108 ... print "creator", r.next()
109 ... return r
110 ...
111 >>> def caller():
112 ... r = creator()
113 ... for i in r:
114 ... print "caller", i
115 ...
116 >>> caller()
117 creator 0
118 caller 1
119 caller 2
120 caller 3
121 caller 4
122
123Generators can call other generators:
124
125 >>> def zrange(n):
126 ... for i in yrange(n):
127 ... yield i
128 ...
129 >>> list(zrange(5))
130 [0, 1, 2, 3, 4]
131
132"""
133
Tim Peters6ba5f792001-06-23 20:45:43 +0000134# The examples from PEP 255.
135
136pep_tests = """
137
138Specification: Return
139
140 Note that return isn't always equivalent to raising StopIteration: the
141 difference lies in how enclosing try/except constructs are treated.
142 For example,
143
144 >>> def f1():
145 ... try:
146 ... return
147 ... except:
148 ... yield 1
149 >>> print list(f1())
150 []
151
152 because, as in any function, return simply exits, but
153
154 >>> def f2():
155 ... try:
156 ... raise StopIteration
157 ... except:
158 ... yield 42
159 >>> print list(f2())
160 [42]
161
162 because StopIteration is captured by a bare "except", as is any
163 exception.
164
165Specification: Generators and Exception Propagation
166
167 >>> def f():
168 ... return 1/0
169 >>> def g():
170 ... yield f() # the zero division exception propagates
171 ... yield 42 # and we'll never get here
172 >>> k = g()
173 >>> k.next()
174 Traceback (most recent call last):
175 File "<stdin>", line 1, in ?
176 File "<stdin>", line 2, in g
177 File "<stdin>", line 2, in f
178 ZeroDivisionError: integer division or modulo by zero
179 >>> k.next() # and the generator cannot be resumed
180 Traceback (most recent call last):
181 File "<stdin>", line 1, in ?
182 StopIteration
183 >>>
184
185Specification: Try/Except/Finally
186
187 >>> def f():
188 ... try:
189 ... yield 1
190 ... try:
191 ... yield 2
192 ... 1/0
193 ... yield 3 # never get here
194 ... except ZeroDivisionError:
195 ... yield 4
196 ... yield 5
197 ... raise
198 ... except:
199 ... yield 6
200 ... yield 7 # the "raise" above stops this
201 ... except:
202 ... yield 8
203 ... yield 9
204 ... try:
205 ... x = 12
206 ... finally:
207 ... yield 10
208 ... yield 11
209 >>> print list(f())
210 [1, 2, 4, 5, 8, 9, 10, 11]
211 >>>
212
Tim Peters6ba5f792001-06-23 20:45:43 +0000213Guido's binary tree example.
214
215 >>> # A binary tree class.
216 >>> class Tree:
217 ...
218 ... def __init__(self, label, left=None, right=None):
219 ... self.label = label
220 ... self.left = left
221 ... self.right = right
222 ...
223 ... def __repr__(self, level=0, indent=" "):
224 ... s = level*indent + `self.label`
225 ... if self.left:
226 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
227 ... if self.right:
228 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
229 ... return s
230 ...
231 ... def __iter__(self):
232 ... return inorder(self)
233
234 >>> # Create a Tree from a list.
235 >>> def tree(list):
236 ... n = len(list)
237 ... if n == 0:
238 ... return []
239 ... i = n / 2
240 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
241
242 >>> # Show it off: create a tree.
243 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
244
245 >>> # A recursive generator that generates Tree leaves in in-order.
246 >>> def inorder(t):
247 ... if t:
248 ... for x in inorder(t.left):
249 ... yield x
250 ... yield t.label
251 ... for x in inorder(t.right):
252 ... yield x
253
254 >>> # Show it off: create a tree.
255 ... t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
256 ... # Print the nodes of the tree in in-order.
257 ... for x in t:
258 ... print x,
259 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
260
261 >>> # A non-recursive generator.
262 >>> def inorder(node):
263 ... stack = []
264 ... while node:
265 ... while node.left:
266 ... stack.append(node)
267 ... node = node.left
268 ... yield node.label
269 ... while not node.right:
270 ... try:
271 ... node = stack.pop()
272 ... except IndexError:
273 ... return
274 ... yield node.label
275 ... node = node.right
276
277 >>> # Exercise the non-recursive generator.
278 >>> for x in t:
279 ... print x,
280 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
281
282"""
283
Tim Petersb2bc6a92001-06-24 10:14:27 +0000284# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000285
286email_tests = """
287
288The difference between yielding None and returning it.
289
290>>> def g():
291... for i in range(3):
292... yield None
293... yield None
294... return
295>>> list(g())
296[None, None, None, None]
297
298Ensure that explicitly raising StopIteration acts like any other exception
299in try/except, not like a return.
300
301>>> def g():
302... yield 1
303... try:
304... raise StopIteration
305... except:
306... yield 2
307... yield 3
308>>> list(g())
309[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000310
311A generator can't be resumed while it's already running.
312
313>>> def g():
314... i = me.next()
315... yield i
316>>> me = g()
317>>> me.next()
318Traceback (most recent call last):
319 ...
320 File "<string>", line 2, in g
321ValueError: generator already executing
Tim Petersb2bc6a92001-06-24 10:14:27 +0000322
323Next one was posted to c.l.py.
324
325>>> def gcomb(x, k):
326... "Generate all combinations of k elements from list x."
327...
328... if k > len(x):
329... return
330... if k == 0:
331... yield []
332... else:
333... first, rest = x[0], x[1:]
334... # A combination does or doesn't contain first.
335... # If it does, the remainder is a k-1 comb of rest.
336... for c in gcomb(rest, k-1):
337... c.insert(0, first)
338... yield c
339... # If it doesn't contain first, it's a k comb of rest.
340... for c in gcomb(rest, k):
341... yield c
342
343>>> seq = range(1, 5)
344>>> for k in range(len(seq) + 2):
345... print "%d-combs of %s:" % (k, seq)
346... for c in gcomb(seq, k):
347... print " ", c
3480-combs of [1, 2, 3, 4]:
349 []
3501-combs of [1, 2, 3, 4]:
351 [1]
352 [2]
353 [3]
354 [4]
3552-combs of [1, 2, 3, 4]:
356 [1, 2]
357 [1, 3]
358 [1, 4]
359 [2, 3]
360 [2, 4]
361 [3, 4]
3623-combs of [1, 2, 3, 4]:
363 [1, 2, 3]
364 [1, 2, 4]
365 [1, 3, 4]
366 [2, 3, 4]
3674-combs of [1, 2, 3, 4]:
368 [1, 2, 3, 4]
3695-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000370
Tim Peterse77f2e22001-06-26 22:24:51 +0000371From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000372
373>>> def g():
374... yield 1
375...
376>>> type(g)
377<type 'function'>
378>>> i = g()
379>>> type(i)
380<type 'generator'>
381>>> dir(i)
Tim Peterse77f2e22001-06-26 22:24:51 +0000382['gi_frame', 'gi_running', 'next']
Tim Peters3e7b1a02001-06-25 19:46:25 +0000383>>> print i.next.__doc__
384next() -- get the next value, or raise StopIteration
385>>> iter(i) is i
3861
387>>> import types
388>>> isinstance(i, types.GeneratorType)
3891
Tim Peterse77f2e22001-06-26 22:24:51 +0000390
391And more, added later.
392
393>>> i.gi_running
3940
395>>> type(i.gi_frame)
396<type 'frame'>
397>>> i.gi_running = 42
398Traceback (most recent call last):
399 ...
400TypeError: object has read-only attributes
401>>> def g():
402... yield me.gi_running
403>>> me = g()
404>>> me.gi_running
4050
406>>> me.next()
4071
408>>> me.gi_running
4090
Tim Peters6ba5f792001-06-23 20:45:43 +0000410"""
411
Tim Peters0f9da0a2001-06-23 21:01:47 +0000412# Fun tests (for sufficiently warped notions of "fun").
413
414fun_tests = """
415
416Build up to a recursive Sieve of Eratosthenes generator.
417
418>>> def firstn(g, n):
419... return [g.next() for i in range(n)]
420
421>>> def intsfrom(i):
422... while 1:
423... yield i
424... i += 1
425
426>>> firstn(intsfrom(5), 7)
427[5, 6, 7, 8, 9, 10, 11]
428
429>>> def exclude_multiples(n, ints):
430... for i in ints:
431... if i % n:
432... yield i
433
434>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
435[1, 2, 4, 5, 7, 8]
436
437>>> def sieve(ints):
438... prime = ints.next()
439... yield prime
440... not_divisible_by_prime = exclude_multiples(prime, ints)
441... for p in sieve(not_divisible_by_prime):
442... yield p
443
444>>> primes = sieve(intsfrom(2))
445>>> firstn(primes, 20)
446[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000447
Tim Petersf6ed0742001-06-27 07:17:57 +0000448
Tim Petersb9e9ff12001-06-24 03:44:52 +0000449Another famous problem: generate all integers of the form
450 2**i * 3**j * 5**k
451in increasing order, where i,j,k >= 0. Trickier than it may look at first!
452Try writing it without generators, and correctly, and without generating
4533 internal results for each result output.
454
455>>> def times(n, g):
456... for i in g:
457... yield n * i
458>>> firstn(times(10, intsfrom(1)), 10)
459[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
460
461>>> def merge(g, h):
462... ng = g.next()
463... nh = h.next()
464... while 1:
465... if ng < nh:
466... yield ng
467... ng = g.next()
468... elif ng > nh:
469... yield nh
470... nh = h.next()
471... else:
472... yield ng
473... ng = g.next()
474... nh = h.next()
475
Tim Petersf6ed0742001-06-27 07:17:57 +0000476The following works, but is doing a whale of a lot of redundant work --
477it's not clear how to get the internal uses of m235 to share a single
478generator. Note that me_times2 (etc) each need to see every element in the
479result sequence. So this is an example where lazy lists are more natural
480(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000481
482>>> def m235():
483... yield 1
484... me_times2 = times(2, m235())
485... me_times3 = times(3, m235())
486... me_times5 = times(5, m235())
487... for i in merge(merge(me_times2,
488... me_times3),
489... me_times5):
490... yield i
491
Tim Petersf6ed0742001-06-27 07:17:57 +0000492Don't print "too many" of these -- the implementation above is extremely
493inefficient: each call of m235() leads to 3 recursive calls, and in
494turn each of those 3 more, and so on, and so on, until we've descended
495enough levels to satisfy the print stmts. Very odd: when I printed 5
496lines of results below, this managed to screw up Win98's malloc in "the
497usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
498address space, and it *looked* like a very slow leak.
499
Tim Petersb9e9ff12001-06-24 03:44:52 +0000500>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000501>>> for i in range(3):
Tim Petersb9e9ff12001-06-24 03:44:52 +0000502... print firstn(result, 15)
503[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
504[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
505[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000506
507Heh. Here's one way to get a shared list, complete with an excruciating
508namespace renaming trick. The *pretty* part is that the times() and merge()
509functions can be reused as-is, because they only assume their stream
510arguments are iterable -- a LazyList is the same as a generator to times().
511
512>>> class LazyList:
513... def __init__(self, g):
514... self.sofar = []
515... self.fetch = g.next
516...
517... def __getitem__(self, i):
518... sofar, fetch = self.sofar, self.fetch
519... while i >= len(sofar):
520... sofar.append(fetch())
521... return sofar[i]
Tim Petersf6ed0742001-06-27 07:17:57 +0000522...
523... def clear(self):
524... self.__dict__.clear()
Tim Petersee309272001-06-24 05:47:06 +0000525
526>>> def m235():
527... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000528... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000529... me_times2 = times(2, m235)
530... me_times3 = times(3, m235)
531... me_times5 = times(5, m235)
532... for i in merge(merge(me_times2,
533... me_times3),
534... me_times5):
535... yield i
536
Tim Petersf6ed0742001-06-27 07:17:57 +0000537Print as many of these as you like -- *this* implementation is memory-
538efficient. XXX Except that it leaks unless you clear the dict!
539
Tim Petersee309272001-06-24 05:47:06 +0000540>>> m235 = LazyList(m235())
541>>> for i in range(5):
542... print [m235[j] for j in range(15*i, 15*(i+1))]
543[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
544[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
545[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
546[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
547[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000548
549>>> m235.clear() # XXX memory leak without this
550
551
552Ye olde Fibonacci generator, LazyList style.
553
554>>> def fibgen(a, b):
555...
556... def sum(g, h):
557... while 1:
558... yield g.next() + h.next()
559...
560... def tail(g):
561... g.next() # throw first away
562... for x in g:
563... yield x
564...
565... yield a
566... yield b
567... for s in sum(iter(fib),
568... tail(iter(fib))):
569... yield s
570
571>>> fib = LazyList(fibgen(1, 2))
572>>> firstn(iter(fib), 17)
573[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
574
575>>> fib.clear() # XXX memory leak without this
Tim Peters0f9da0a2001-06-23 21:01:47 +0000576"""
577
Tim Petersb6c3cea2001-06-26 03:36:28 +0000578# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
579# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000580
Tim Petersea2e97a2001-06-24 07:10:02 +0000581syntax_tests = """
582
583>>> def f():
584... return 22
585... yield 1
586Traceback (most recent call last):
587 ...
588SyntaxError: 'return' with argument inside generator (<string>, line 2)
589
590>>> def f():
591... yield 1
592... return 22
593Traceback (most recent call last):
594 ...
595SyntaxError: 'return' with argument inside generator (<string>, line 3)
596
597"return None" is not the same as "return" in a generator:
598
599>>> def f():
600... yield 1
601... return None
602Traceback (most recent call last):
603 ...
604SyntaxError: 'return' with argument inside generator (<string>, line 3)
605
606This one is fine:
607
608>>> def f():
609... yield 1
610... return
611
612>>> def f():
613... try:
614... yield 1
615... finally:
616... pass
617Traceback (most recent call last):
618 ...
619SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<string>, line 3)
620
621>>> def f():
622... try:
623... try:
624... 1/0
625... except ZeroDivisionError:
626... yield 666 # bad because *outer* try has finally
627... except:
628... pass
629... finally:
630... pass
631Traceback (most recent call last):
632 ...
633SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<string>, line 6)
634
635But this is fine:
636
637>>> def f():
638... try:
639... try:
640... yield 12
641... 1/0
642... except ZeroDivisionError:
643... yield 666
644... except:
645... try:
646... x = 12
647... finally:
648... yield 12
649... except:
650... return
651>>> list(f())
652[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000653
654>>> def f():
655... if 0:
656... yield 1
657>>> type(f())
658<type 'generator'>
659
660>>> def f():
661... if "":
662... yield None
663>>> type(f())
664<type 'generator'>
665
666>>> def f():
667... return
668... try:
669... if x==4:
670... pass
671... elif 0:
672... try:
673... 1/0
674... except SyntaxError:
675... pass
676... else:
677... if 0:
678... while 12:
679... x += 1
680... yield 2 # don't blink
681... f(a, b, c, d, e)
682... else:
683... pass
684... except:
685... x = 1
686... return
687>>> type(f())
688<type 'generator'>
689
690>>> def f():
691... if 0:
692... def g():
693... yield 1
694...
695>>> type(f())
696<type 'None'>
697
698>>> def f():
699... if 0:
700... class C:
701... def __init__(self):
702... yield 1
703... def f(self):
704... yield 2
705>>> type(f())
706<type 'None'>
Tim Petersea2e97a2001-06-24 07:10:02 +0000707"""
708
Tim Petersf6ed0742001-06-27 07:17:57 +0000709__test__ = {"tut": tutorial_tests,
710 "pep": pep_tests,
711 "email": email_tests,
712 "fun": fun_tests,
713 "syntax": syntax_tests}
Tim Peters1def3512001-06-23 20:27:04 +0000714
715# Magic test name that regrtest.py invokes *after* importing this module.
716# This worms around a bootstrap problem.
717# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
718# so this works as expected in both ways of running regrtest.
719def test_main():
720 import doctest, test_generators
Tim Peters2106ef02001-06-25 01:30:12 +0000721 if 0:
722 # Temporary block to help track down leaks. So far, the blame
Tim Petersf6ed0742001-06-27 07:17:57 +0000723 # fell mostly on doctest. Later: the only leaks remaining are
724 # in fun_tests, and only if you comment out the two LazyList.clear()
725 # calls.
726 for i in range(10000):
Tim Peters2106ef02001-06-25 01:30:12 +0000727 doctest.master = None
728 doctest.testmod(test_generators)
729 else:
730 doctest.testmod(test_generators)
Tim Peters1def3512001-06-23 20:27:04 +0000731
732# This part isn't needed for regrtest, but for running the test directly.
733if __name__ == "__main__":
734 test_main()