blob: 3646001abab2776a5447acf4766f5f5d924c506f [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
371# From the Iterators list, about the types of these things.
372
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)
382['next']
383>>> 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 Peters6ba5f792001-06-23 20:45:43 +0000390"""
391
Tim Peters0f9da0a2001-06-23 21:01:47 +0000392# Fun tests (for sufficiently warped notions of "fun").
393
394fun_tests = """
395
396Build up to a recursive Sieve of Eratosthenes generator.
397
398>>> def firstn(g, n):
399... return [g.next() for i in range(n)]
400
401>>> def intsfrom(i):
402... while 1:
403... yield i
404... i += 1
405
406>>> firstn(intsfrom(5), 7)
407[5, 6, 7, 8, 9, 10, 11]
408
409>>> def exclude_multiples(n, ints):
410... for i in ints:
411... if i % n:
412... yield i
413
414>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
415[1, 2, 4, 5, 7, 8]
416
417>>> def sieve(ints):
418... prime = ints.next()
419... yield prime
420... not_divisible_by_prime = exclude_multiples(prime, ints)
421... for p in sieve(not_divisible_by_prime):
422... yield p
423
424>>> primes = sieve(intsfrom(2))
425>>> firstn(primes, 20)
426[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 +0000427
428Another famous problem: generate all integers of the form
429 2**i * 3**j * 5**k
430in increasing order, where i,j,k >= 0. Trickier than it may look at first!
431Try writing it without generators, and correctly, and without generating
4323 internal results for each result output.
433
Tim Petersb6c3cea2001-06-26 03:36:28 +0000434XXX Suspect there's memory leaks in this one; definitely in the next
435XXX version.
436
Tim Petersb9e9ff12001-06-24 03:44:52 +0000437>>> def times(n, g):
438... for i in g:
439... yield n * i
440>>> firstn(times(10, intsfrom(1)), 10)
441[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
442
443>>> def merge(g, h):
444... ng = g.next()
445... nh = h.next()
446... while 1:
447... if ng < nh:
448... yield ng
449... ng = g.next()
450... elif ng > nh:
451... yield nh
452... nh = h.next()
453... else:
454... yield ng
455... ng = g.next()
456... nh = h.next()
457
458This works, but is doing a whale of a lot or redundant work -- it's not
459clear how to get the internal uses of m235 to share a single generator.
460Note that me_times2 (etc) each need to see every element in the result
461sequence. So this is an example where lazy lists are more natural (you
462can look at the head of a lazy list any number of times).
463
464>>> def m235():
465... yield 1
466... me_times2 = times(2, m235())
467... me_times3 = times(3, m235())
468... me_times5 = times(5, m235())
469... for i in merge(merge(me_times2,
470... me_times3),
471... me_times5):
472... yield i
473
474>>> result = m235()
475>>> for i in range(5):
476... print firstn(result, 15)
477[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
478[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
479[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
480[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
481[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersee309272001-06-24 05:47:06 +0000482
483Heh. Here's one way to get a shared list, complete with an excruciating
484namespace renaming trick. The *pretty* part is that the times() and merge()
485functions can be reused as-is, because they only assume their stream
486arguments are iterable -- a LazyList is the same as a generator to times().
487
Tim Petersb6c3cea2001-06-26 03:36:28 +0000488XXX Massive memory leaks in this; see Python-Iterators.
489
Tim Petersee309272001-06-24 05:47:06 +0000490>>> class LazyList:
491... def __init__(self, g):
492... self.sofar = []
493... self.fetch = g.next
494...
495... def __getitem__(self, i):
496... sofar, fetch = self.sofar, self.fetch
497... while i >= len(sofar):
498... sofar.append(fetch())
499... return sofar[i]
500
501>>> def m235():
502... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000503... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000504... me_times2 = times(2, m235)
505... me_times3 = times(3, m235)
506... me_times5 = times(5, m235)
507... for i in merge(merge(me_times2,
508... me_times3),
509... me_times5):
510... yield i
511
512>>> m235 = LazyList(m235())
513>>> for i in range(5):
514... print [m235[j] for j in range(15*i, 15*(i+1))]
515[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
516[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
517[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
518[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
519[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000520"""
521
Tim Petersb6c3cea2001-06-26 03:36:28 +0000522# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
523# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000524
Tim Petersea2e97a2001-06-24 07:10:02 +0000525syntax_tests = """
526
527>>> def f():
528... return 22
529... yield 1
530Traceback (most recent call last):
531 ...
532SyntaxError: 'return' with argument inside generator (<string>, line 2)
533
534>>> def f():
535... yield 1
536... return 22
537Traceback (most recent call last):
538 ...
539SyntaxError: 'return' with argument inside generator (<string>, line 3)
540
541"return None" is not the same as "return" in a generator:
542
543>>> def f():
544... yield 1
545... return None
546Traceback (most recent call last):
547 ...
548SyntaxError: 'return' with argument inside generator (<string>, line 3)
549
550This one is fine:
551
552>>> def f():
553... yield 1
554... return
555
556>>> def f():
557... try:
558... yield 1
559... finally:
560... pass
561Traceback (most recent call last):
562 ...
563SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<string>, line 3)
564
565>>> def f():
566... try:
567... try:
568... 1/0
569... except ZeroDivisionError:
570... yield 666 # bad because *outer* try has finally
571... except:
572... pass
573... finally:
574... pass
575Traceback (most recent call last):
576 ...
577SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<string>, line 6)
578
579But this is fine:
580
581>>> def f():
582... try:
583... try:
584... yield 12
585... 1/0
586... except ZeroDivisionError:
587... yield 666
588... except:
589... try:
590... x = 12
591... finally:
592... yield 12
593... except:
594... return
595>>> list(f())
596[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000597
598>>> def f():
599... if 0:
600... yield 1
601>>> type(f())
602<type 'generator'>
603
604>>> def f():
605... if "":
606... yield None
607>>> type(f())
608<type 'generator'>
609
610>>> def f():
611... return
612... try:
613... if x==4:
614... pass
615... elif 0:
616... try:
617... 1/0
618... except SyntaxError:
619... pass
620... else:
621... if 0:
622... while 12:
623... x += 1
624... yield 2 # don't blink
625... f(a, b, c, d, e)
626... else:
627... pass
628... except:
629... x = 1
630... return
631>>> type(f())
632<type 'generator'>
633
634>>> def f():
635... if 0:
636... def g():
637... yield 1
638...
639>>> type(f())
640<type 'None'>
641
642>>> def f():
643... if 0:
644... class C:
645... def __init__(self):
646... yield 1
647... def f(self):
648... yield 2
649>>> type(f())
650<type 'None'>
Tim Petersea2e97a2001-06-24 07:10:02 +0000651"""
652
Tim Petersb6c3cea2001-06-26 03:36:28 +0000653
654x_tests = """
655
656>>> def firstn(g, n):
657... return [g.next() for i in range(n)]
658
659>>> def times(n, g):
660... for i in g:
661... yield n * i
662
663>>> def merge(g, h):
664... ng = g.next()
665... nh = h.next()
666... while 1:
667... if ng < nh:
668... yield ng
669... ng = g.next()
670... elif ng > nh:
671... yield nh
672... nh = h.next()
673... else:
674... yield ng
675... ng = g.next()
676... nh = h.next()
677
678>>> class LazyList:
679... def __init__(self, g):
680... self.sofar = []
681... self.fetch = g.next
682...
683... def __getitem__(self, i):
684... sofar, fetch = self.sofar, self.fetch
685... while i >= len(sofar):
686... sofar.append(fetch())
687... return sofar[i]
688
689>>> def m235():
690... yield 1
691... # Gack: m235 below actually refers to a LazyList.
692... me_times2 = times(2, m235)
693... me_times3 = times(3, m235)
694... me_times5 = times(5, m235)
695... for i in merge(merge(me_times2,
696... me_times3),
697... me_times5):
698... yield i
699
700>>> m235 = LazyList(m235())
701>>> for i in range(5):
702... x = [m235[j] for j in range(15*i, 15*(i+1))]
703
704
705[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
706[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
707[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
708[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
709[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
710"""
711
712__test__ = {"tut": tutorial_tests, # clean
713 "pep": pep_tests, # clean
714 "email": email_tests, # clean
715 "fun": fun_tests, # leaks
716 "syntax": syntax_tests # clean
717 #"x": x_tests
718}
Tim Peters1def3512001-06-23 20:27:04 +0000719
720# Magic test name that regrtest.py invokes *after* importing this module.
721# This worms around a bootstrap problem.
722# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
723# so this works as expected in both ways of running regrtest.
724def test_main():
725 import doctest, test_generators
Tim Peters2106ef02001-06-25 01:30:12 +0000726 if 0:
727 # Temporary block to help track down leaks. So far, the blame
728 # has fallen mostly on doctest.
Tim Petersb6c3cea2001-06-26 03:36:28 +0000729 for i in range(5000):
Tim Peters2106ef02001-06-25 01:30:12 +0000730 doctest.master = None
731 doctest.testmod(test_generators)
732 else:
733 doctest.testmod(test_generators)
Tim Peters1def3512001-06-23 20:27:04 +0000734
735# This part isn't needed for regrtest, but for running the test directly.
736if __name__ == "__main__":
737 test_main()