blob: 4b2ed8fff41a0f2d000553b881a8443374053b2b [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
Tim Peters34463652001-07-12 22:43:41 +000050 ... raise StopIteration
Tim Peters1def3512001-06-23 20:27:04 +000051 ... 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
Tim Peterse5614632001-08-15 04:41:19 +0000138Specification: Yield
139
140 Restriction: A generator cannot be resumed while it is actively
141 running:
142
143 >>> def g():
144 ... i = me.next()
145 ... yield i
146 >>> me = g()
147 >>> me.next()
148 Traceback (most recent call last):
149 ...
150 File "<string>", line 2, in g
151 ValueError: generator already executing
152
Tim Peters6ba5f792001-06-23 20:45:43 +0000153Specification: Return
154
155 Note that return isn't always equivalent to raising StopIteration: the
156 difference lies in how enclosing try/except constructs are treated.
157 For example,
158
159 >>> def f1():
160 ... try:
161 ... return
162 ... except:
163 ... yield 1
164 >>> print list(f1())
165 []
166
167 because, as in any function, return simply exits, but
168
169 >>> def f2():
170 ... try:
171 ... raise StopIteration
172 ... except:
173 ... yield 42
174 >>> print list(f2())
175 [42]
176
177 because StopIteration is captured by a bare "except", as is any
178 exception.
179
180Specification: Generators and Exception Propagation
181
182 >>> def f():
Tim Peters3caca232001-12-06 06:23:26 +0000183 ... return 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000184 >>> def g():
185 ... yield f() # the zero division exception propagates
186 ... yield 42 # and we'll never get here
187 >>> k = g()
188 >>> k.next()
189 Traceback (most recent call last):
190 File "<stdin>", line 1, in ?
191 File "<stdin>", line 2, in g
192 File "<stdin>", line 2, in f
193 ZeroDivisionError: integer division or modulo by zero
194 >>> k.next() # and the generator cannot be resumed
195 Traceback (most recent call last):
196 File "<stdin>", line 1, in ?
197 StopIteration
198 >>>
199
200Specification: Try/Except/Finally
201
202 >>> def f():
203 ... try:
204 ... yield 1
205 ... try:
206 ... yield 2
Tim Peters3caca232001-12-06 06:23:26 +0000207 ... 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000208 ... yield 3 # never get here
209 ... except ZeroDivisionError:
210 ... yield 4
211 ... yield 5
212 ... raise
213 ... except:
214 ... yield 6
215 ... yield 7 # the "raise" above stops this
216 ... except:
217 ... yield 8
218 ... yield 9
219 ... try:
220 ... x = 12
221 ... finally:
222 ... yield 10
223 ... yield 11
224 >>> print list(f())
225 [1, 2, 4, 5, 8, 9, 10, 11]
226 >>>
227
Tim Peters6ba5f792001-06-23 20:45:43 +0000228Guido's binary tree example.
229
230 >>> # A binary tree class.
231 >>> class Tree:
232 ...
233 ... def __init__(self, label, left=None, right=None):
234 ... self.label = label
235 ... self.left = left
236 ... self.right = right
237 ...
238 ... def __repr__(self, level=0, indent=" "):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000239 ... s = level*indent + repr(self.label)
Tim Peters6ba5f792001-06-23 20:45:43 +0000240 ... if self.left:
241 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
242 ... if self.right:
243 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
244 ... return s
245 ...
246 ... def __iter__(self):
247 ... return inorder(self)
248
249 >>> # Create a Tree from a list.
250 >>> def tree(list):
251 ... n = len(list)
252 ... if n == 0:
253 ... return []
Tim Peters3caca232001-12-06 06:23:26 +0000254 ... i = n // 2
Tim Peters6ba5f792001-06-23 20:45:43 +0000255 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
256
257 >>> # Show it off: create a tree.
258 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
259
Tim Petersd674e172002-03-10 07:59:13 +0000260 >>> # A recursive generator that generates Tree labels in in-order.
Tim Peters6ba5f792001-06-23 20:45:43 +0000261 >>> def inorder(t):
262 ... if t:
263 ... for x in inorder(t.left):
264 ... yield x
265 ... yield t.label
266 ... for x in inorder(t.right):
267 ... yield x
268
269 >>> # Show it off: create a tree.
Edward Loper103d26e2004-08-09 02:03:30 +0000270 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
271 >>> # Print the nodes of the tree in in-order.
272 >>> for x in t:
Tim Peters6ba5f792001-06-23 20:45:43 +0000273 ... 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 >>> # A non-recursive generator.
277 >>> def inorder(node):
278 ... stack = []
279 ... while node:
280 ... while node.left:
281 ... stack.append(node)
282 ... node = node.left
283 ... yield node.label
284 ... while not node.right:
285 ... try:
286 ... node = stack.pop()
287 ... except IndexError:
288 ... return
289 ... yield node.label
290 ... node = node.right
291
292 >>> # Exercise the non-recursive generator.
293 >>> for x in t:
294 ... print x,
295 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
296
297"""
298
Tim Petersb2bc6a92001-06-24 10:14:27 +0000299# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000300
301email_tests = """
302
303The difference between yielding None and returning it.
304
305>>> def g():
306... for i in range(3):
307... yield None
308... yield None
309... return
310>>> list(g())
311[None, None, None, None]
312
313Ensure that explicitly raising StopIteration acts like any other exception
314in try/except, not like a return.
315
316>>> def g():
317... yield 1
318... try:
319... raise StopIteration
320... except:
321... yield 2
322... yield 3
323>>> list(g())
324[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000325
Tim Petersb2bc6a92001-06-24 10:14:27 +0000326Next one was posted to c.l.py.
327
328>>> def gcomb(x, k):
329... "Generate all combinations of k elements from list x."
330...
331... if k > len(x):
332... return
333... if k == 0:
334... yield []
335... else:
336... first, rest = x[0], x[1:]
337... # A combination does or doesn't contain first.
338... # If it does, the remainder is a k-1 comb of rest.
339... for c in gcomb(rest, k-1):
340... c.insert(0, first)
341... yield c
342... # If it doesn't contain first, it's a k comb of rest.
343... for c in gcomb(rest, k):
344... yield c
345
346>>> seq = range(1, 5)
347>>> for k in range(len(seq) + 2):
348... print "%d-combs of %s:" % (k, seq)
349... for c in gcomb(seq, k):
350... print " ", c
3510-combs of [1, 2, 3, 4]:
352 []
3531-combs of [1, 2, 3, 4]:
354 [1]
355 [2]
356 [3]
357 [4]
3582-combs of [1, 2, 3, 4]:
359 [1, 2]
360 [1, 3]
361 [1, 4]
362 [2, 3]
363 [2, 4]
364 [3, 4]
3653-combs of [1, 2, 3, 4]:
366 [1, 2, 3]
367 [1, 2, 4]
368 [1, 3, 4]
369 [2, 3, 4]
3704-combs of [1, 2, 3, 4]:
371 [1, 2, 3, 4]
3725-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000373
Tim Peterse77f2e22001-06-26 22:24:51 +0000374From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000375
376>>> def g():
377... yield 1
378...
379>>> type(g)
380<type 'function'>
381>>> i = g()
382>>> type(i)
383<type 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000384>>> [s for s in dir(i) if not s.startswith('_')]
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000385['close', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
Tim Peters3e7b1a02001-06-25 19:46:25 +0000386>>> print i.next.__doc__
Tim Peters6d6c1a32001-08-02 04:15:00 +0000387x.next() -> the next value, or raise StopIteration
Tim Peters3e7b1a02001-06-25 19:46:25 +0000388>>> iter(i) is i
Guido van Rossum77f6a652002-04-03 22:41:51 +0000389True
Tim Peters3e7b1a02001-06-25 19:46:25 +0000390>>> import types
391>>> isinstance(i, types.GeneratorType)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000392True
Tim Peterse77f2e22001-06-26 22:24:51 +0000393
394And more, added later.
395
396>>> i.gi_running
3970
398>>> type(i.gi_frame)
399<type 'frame'>
400>>> i.gi_running = 42
401Traceback (most recent call last):
402 ...
Guido van Rossum61cf7802001-08-10 21:25:24 +0000403TypeError: readonly attribute
Tim Peterse77f2e22001-06-26 22:24:51 +0000404>>> def g():
405... yield me.gi_running
406>>> me = g()
407>>> me.gi_running
4080
409>>> me.next()
4101
411>>> me.gi_running
4120
Tim Peters35302662001-07-02 01:38:33 +0000413
414A clever union-find implementation from c.l.py, due to David Eppstein.
415Sent: Friday, June 29, 2001 12:16 PM
416To: python-list@python.org
417Subject: Re: PEP 255: Simple Generators
418
419>>> class disjointSet:
420... def __init__(self, name):
421... self.name = name
422... self.parent = None
423... self.generator = self.generate()
424...
425... def generate(self):
426... while not self.parent:
427... yield self
428... for x in self.parent.generator:
429... yield x
430...
431... def find(self):
432... return self.generator.next()
433...
434... def union(self, parent):
435... if self.parent:
436... raise ValueError("Sorry, I'm not a root!")
437... self.parent = parent
438...
439... def __str__(self):
440... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000441
442>>> names = "ABCDEFGHIJKLM"
443>>> sets = [disjointSet(name) for name in names]
444>>> roots = sets[:]
445
446>>> import random
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000447>>> gen = random.WichmannHill(42)
Tim Peters35302662001-07-02 01:38:33 +0000448>>> while 1:
449... for s in sets:
450... print "%s->%s" % (s, s.find()),
451... print
452... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000453... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000454... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000455... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000456... s1.union(s2)
457... print "merged", s1, "into", s2
458... else:
459... break
460A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->M
461merged D into G
462A->A B->B C->C D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
463merged C into F
464A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
465merged L into A
466A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->A M->M
467merged H into E
468A->A B->B C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
469merged B into E
470A->A B->E C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
471merged J into G
472A->A B->E C->F D->G E->E F->F G->G H->E I->I J->G K->K L->A M->M
473merged E into G
474A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->M
475merged M into G
476A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->G
477merged I into K
478A->A B->G C->F D->G E->G F->F G->G H->G I->K J->G K->K L->A M->G
479merged K into A
480A->A B->G C->F D->G E->G F->F G->G H->G I->A J->G K->A L->A M->G
481merged F into A
482A->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G
483merged A into G
484A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000485
Tim Peters6ba5f792001-06-23 20:45:43 +0000486"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000487# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000488
Tim Peters0f9da0a2001-06-23 21:01:47 +0000489# Fun tests (for sufficiently warped notions of "fun").
490
491fun_tests = """
492
493Build up to a recursive Sieve of Eratosthenes generator.
494
495>>> def firstn(g, n):
496... return [g.next() for i in range(n)]
497
498>>> def intsfrom(i):
499... while 1:
500... yield i
501... i += 1
502
503>>> firstn(intsfrom(5), 7)
504[5, 6, 7, 8, 9, 10, 11]
505
506>>> def exclude_multiples(n, ints):
507... for i in ints:
508... if i % n:
509... yield i
510
511>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
512[1, 2, 4, 5, 7, 8]
513
514>>> def sieve(ints):
515... prime = ints.next()
516... yield prime
517... not_divisible_by_prime = exclude_multiples(prime, ints)
518... for p in sieve(not_divisible_by_prime):
519... yield p
520
521>>> primes = sieve(intsfrom(2))
522>>> firstn(primes, 20)
523[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 +0000524
Tim Petersf6ed0742001-06-27 07:17:57 +0000525
Tim Petersb9e9ff12001-06-24 03:44:52 +0000526Another famous problem: generate all integers of the form
527 2**i * 3**j * 5**k
528in increasing order, where i,j,k >= 0. Trickier than it may look at first!
529Try writing it without generators, and correctly, and without generating
5303 internal results for each result output.
531
532>>> def times(n, g):
533... for i in g:
534... yield n * i
535>>> firstn(times(10, intsfrom(1)), 10)
536[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
537
538>>> def merge(g, h):
539... ng = g.next()
540... nh = h.next()
541... while 1:
542... if ng < nh:
543... yield ng
544... ng = g.next()
545... elif ng > nh:
546... yield nh
547... nh = h.next()
548... else:
549... yield ng
550... ng = g.next()
551... nh = h.next()
552
Tim Petersf6ed0742001-06-27 07:17:57 +0000553The following works, but is doing a whale of a lot of redundant work --
554it's not clear how to get the internal uses of m235 to share a single
555generator. Note that me_times2 (etc) each need to see every element in the
556result sequence. So this is an example where lazy lists are more natural
557(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000558
559>>> def m235():
560... yield 1
561... me_times2 = times(2, m235())
562... me_times3 = times(3, m235())
563... me_times5 = times(5, m235())
564... for i in merge(merge(me_times2,
565... me_times3),
566... me_times5):
567... yield i
568
Tim Petersf6ed0742001-06-27 07:17:57 +0000569Don't print "too many" of these -- the implementation above is extremely
570inefficient: each call of m235() leads to 3 recursive calls, and in
571turn each of those 3 more, and so on, and so on, until we've descended
572enough levels to satisfy the print stmts. Very odd: when I printed 5
573lines of results below, this managed to screw up Win98's malloc in "the
574usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
575address space, and it *looked* like a very slow leak.
576
Tim Petersb9e9ff12001-06-24 03:44:52 +0000577>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000578>>> for i in range(3):
Tim Petersb9e9ff12001-06-24 03:44:52 +0000579... print firstn(result, 15)
580[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
581[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
582[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000583
584Heh. Here's one way to get a shared list, complete with an excruciating
585namespace renaming trick. The *pretty* part is that the times() and merge()
586functions can be reused as-is, because they only assume their stream
587arguments are iterable -- a LazyList is the same as a generator to times().
588
589>>> class LazyList:
590... def __init__(self, g):
591... self.sofar = []
592... self.fetch = g.next
593...
594... def __getitem__(self, i):
595... sofar, fetch = self.sofar, self.fetch
596... while i >= len(sofar):
597... sofar.append(fetch())
598... return sofar[i]
599
600>>> def m235():
601... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000602... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000603... me_times2 = times(2, m235)
604... me_times3 = times(3, m235)
605... me_times5 = times(5, m235)
606... for i in merge(merge(me_times2,
607... me_times3),
608... me_times5):
609... yield i
610
Tim Petersf6ed0742001-06-27 07:17:57 +0000611Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000612efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000613
Tim Petersee309272001-06-24 05:47:06 +0000614>>> m235 = LazyList(m235())
615>>> for i in range(5):
616... print [m235[j] for j in range(15*i, 15*(i+1))]
617[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
618[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
619[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
620[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
621[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000622
Tim Petersf6ed0742001-06-27 07:17:57 +0000623Ye olde Fibonacci generator, LazyList style.
624
625>>> def fibgen(a, b):
626...
627... def sum(g, h):
628... while 1:
629... yield g.next() + h.next()
630...
631... def tail(g):
632... g.next() # throw first away
633... for x in g:
634... yield x
635...
636... yield a
637... yield b
638... for s in sum(iter(fib),
639... tail(iter(fib))):
640... yield s
641
642>>> fib = LazyList(fibgen(1, 2))
643>>> firstn(iter(fib), 17)
644[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Georg Brandl52715f62005-08-24 09:02:29 +0000645
646
647Running after your tail with itertools.tee (new in version 2.4)
648
649The algorithms "m235" (Hamming) and Fibonacci presented above are both
650examples of a whole family of FP (functional programming) algorithms
651where a function produces and returns a list while the production algorithm
652suppose the list as already produced by recursively calling itself.
653For these algorithms to work, they must:
654
655- produce at least a first element without presupposing the existence of
656 the rest of the list
657- produce their elements in a lazy manner
658
659To work efficiently, the beginning of the list must not be recomputed over
660and over again. This is ensured in most FP languages as a built-in feature.
661In python, we have to explicitly maintain a list of already computed results
662and abandon genuine recursivity.
663
664This is what had been attempted above with the LazyList class. One problem
665with that class is that it keeps a list of all of the generated results and
666therefore continually grows. This partially defeats the goal of the generator
667concept, viz. produce the results only as needed instead of producing them
668all and thereby wasting memory.
669
670Thanks to itertools.tee, it is now clear "how to get the internal uses of
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000671m235 to share a single generator". Unfortunately, using generators this way
672creates a reference-cycle that the garbage collector (currently) can't clean
673up, so we have to explicitly break the cycle (by calling the inner
674generator's close() method)
Georg Brandl52715f62005-08-24 09:02:29 +0000675
676>>> from itertools import tee
677>>> def m235():
678... def _m235():
679... yield 1
680... for n in merge(times(2, m2),
681... merge(times(3, m3),
682... times(5, m5))):
683... yield n
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000684... m1 = _m235()
685... m2, m3, m5, mRes = tee(m1, 4)
686... return m1.close, mRes
Georg Brandl52715f62005-08-24 09:02:29 +0000687
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000688>>> closer, it = m235()
Georg Brandl52715f62005-08-24 09:02:29 +0000689>>> for i in range(5):
690... print firstn(it, 15)
691[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
692[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
693[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
694[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
695[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000696>>> closer()
Georg Brandl52715f62005-08-24 09:02:29 +0000697
698The "tee" function does just what we want. It internally keeps a generated
699result for as long as it has not been "consumed" from all of the duplicated
700iterators, whereupon it is deleted. You can therefore print the hamming
701sequence during hours without increasing memory usage, or very little.
702
Tim Peters7f098112006-04-15 01:48:57 +0000703The beauty of it is that recursive running-after-their-tail FP algorithms
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000704are quite straightforwardly expressed with this Python idiom. The problem is
Tim Peters7f098112006-04-15 01:48:57 +0000705that this creates an uncollectable reference cycle, and we have to explicitly
706close the innermost generator to clean up the cycle.
707XXX As of 14-Apr-2006, Tim doubts that anyone understands _why_ some cycle
708XXX is uncollectable here.
Georg Brandl52715f62005-08-24 09:02:29 +0000709
710Ye olde Fibonacci generator, tee style.
711
712>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +0000713...
Georg Brandl52715f62005-08-24 09:02:29 +0000714... def _isum(g, h):
715... while 1:
716... yield g.next() + h.next()
Tim Peters9e34c042005-08-26 15:20:46 +0000717...
Georg Brandl52715f62005-08-24 09:02:29 +0000718... def _fib():
719... yield 1
720... yield 2
721... fibTail.next() # throw first away
722... for res in _isum(fibHead, fibTail):
723... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000724...
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000725... realfib = _fib()
726... fibHead, fibTail, fibRes = tee(realfib, 3)
727... return realfib.close, fibRes
Georg Brandl52715f62005-08-24 09:02:29 +0000728
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000729>>> closer, fibber = fib()
730>>> firstn(fibber, 17)
Georg Brandl52715f62005-08-24 09:02:29 +0000731[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000732>>> closer()
Georg Brandl52715f62005-08-24 09:02:29 +0000733
Tim Peters7f098112006-04-15 01:48:57 +0000734XXX Again the tee-based approach leaks without an explicit close().
Tim Peters0f9da0a2001-06-23 21:01:47 +0000735"""
736
Neal Norwitzcde87502006-04-14 06:11:08 +0000737leak_test1 = """
738
739This test leaked at one point due to generator finalization/destruction.
740It was copied from Lib/test/leakers/test_generator_cycle.py before the file
741was removed.
742
743>>> def leak():
744... def gen():
745... while True:
746... yield g
747... g = gen()
748
749>>> leak()
750
751"""
752
Tim Petersb6c3cea2001-06-26 03:36:28 +0000753# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
754# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000755
Tim Petersea2e97a2001-06-24 07:10:02 +0000756syntax_tests = """
757
Tim Petersaef8cfa2004-08-27 15:12:49 +0000758>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000759... return 22
760... yield 1
761Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000762 ..
Tim Petersc5684782004-09-13 01:07:12 +0000763SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2)
Tim Petersea2e97a2001-06-24 07:10:02 +0000764
Tim Petersaef8cfa2004-08-27 15:12:49 +0000765>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000766... yield 1
767... return 22
768Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000769 ..
Tim Petersc5684782004-09-13 01:07:12 +0000770SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000771
772"return None" is not the same as "return" in a generator:
773
Tim Petersaef8cfa2004-08-27 15:12:49 +0000774>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000775... yield 1
776... return None
777Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000778 ..
Tim Petersc5684782004-09-13 01:07:12 +0000779SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000780
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000781These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000782
783>>> def f():
784... yield 1
785... return
786
Tim Petersaef8cfa2004-08-27 15:12:49 +0000787>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000788... try:
789... yield 1
790... finally:
791... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000792
Tim Petersaef8cfa2004-08-27 15:12:49 +0000793>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000794... try:
795... try:
Tim Peters3caca232001-12-06 06:23:26 +0000796... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000797... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000798... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000799... except:
800... pass
801... finally:
802... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000803
804>>> def f():
805... try:
806... try:
807... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000808... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000809... except ZeroDivisionError:
810... yield 666
811... except:
812... try:
813... x = 12
814... finally:
815... yield 12
816... except:
817... return
818>>> list(f())
819[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000820
821>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000822... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000823>>> type(f())
824<type 'generator'>
825
Tim Peters08a898f2001-06-28 01:52:22 +0000826
827>>> def f():
828... if 0:
829... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000830>>> type(f())
831<type 'generator'>
832
Tim Peters08a898f2001-06-28 01:52:22 +0000833
834>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000835... if 0:
836... yield 1
837>>> type(f())
838<type 'generator'>
839
840>>> def f():
841... if "":
842... yield None
843>>> type(f())
844<type 'generator'>
845
846>>> def f():
847... return
848... try:
849... if x==4:
850... pass
851... elif 0:
852... try:
Tim Peters3caca232001-12-06 06:23:26 +0000853... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000854... except SyntaxError:
855... pass
856... else:
857... if 0:
858... while 12:
859... x += 1
860... yield 2 # don't blink
861... f(a, b, c, d, e)
862... else:
863... pass
864... except:
865... x = 1
866... return
867>>> type(f())
868<type 'generator'>
869
870>>> def f():
871... if 0:
872... def g():
873... yield 1
874...
875>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000876<type 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000877
878>>> def f():
879... if 0:
880... class C:
881... def __init__(self):
882... yield 1
883... def f(self):
884... yield 2
885>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000886<type 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000887
888>>> def f():
889... if 0:
890... return
891... if 0:
892... yield 2
893>>> type(f())
894<type 'generator'>
895
896
Tim Petersaef8cfa2004-08-27 15:12:49 +0000897>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000898... if 0:
899... lambda x: x # shouldn't trigger here
900... return # or here
901... def f(i):
902... return 2*i # or here
903... if 0:
904... return 3 # but *this* sucks (line 8)
905... if 0:
906... yield 2 # because it's a generator
907Traceback (most recent call last):
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000908SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 8)
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000909
910This one caused a crash (see SF bug 567538):
911
912>>> def f():
913... for i in range(3):
914... try:
915... continue
916... finally:
917... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000918...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000919>>> g = f()
920>>> print g.next()
9210
922>>> print g.next()
9231
924>>> print g.next()
9252
926>>> print g.next()
927Traceback (most recent call last):
928StopIteration
Tim Petersea2e97a2001-06-24 07:10:02 +0000929"""
930
Tim Petersbe4f0a72001-06-29 02:41:16 +0000931# conjoin is a simple backtracking generator, named in honor of Icon's
932# "conjunction" control structure. Pass a list of no-argument functions
933# that return iterable objects. Easiest to explain by example: assume the
934# function list [x, y, z] is passed. Then conjoin acts like:
935#
936# def g():
937# values = [None] * 3
938# for values[0] in x():
939# for values[1] in y():
940# for values[2] in z():
941# yield values
942#
943# So some 3-lists of values *may* be generated, each time we successfully
944# get into the innermost loop. If an iterator fails (is exhausted) before
945# then, it "backtracks" to get the next value from the nearest enclosing
946# iterator (the one "to the left"), and starts all over again at the next
947# slot (pumps a fresh iterator). Of course this is most useful when the
948# iterators have side-effects, so that which values *can* be generated at
949# each slot depend on the values iterated at previous slots.
950
951def conjoin(gs):
952
953 values = [None] * len(gs)
954
955 def gen(i, values=values):
956 if i >= len(gs):
957 yield values
958 else:
959 for values[i] in gs[i]():
960 for x in gen(i+1):
961 yield x
962
963 for x in gen(0):
964 yield x
965
Tim Petersc468fd22001-06-30 07:29:44 +0000966# That works fine, but recursing a level and checking i against len(gs) for
967# each item produced is inefficient. By doing manual loop unrolling across
968# generator boundaries, it's possible to eliminate most of that overhead.
969# This isn't worth the bother *in general* for generators, but conjoin() is
970# a core building block for some CPU-intensive generator applications.
971
972def conjoin(gs):
973
974 n = len(gs)
975 values = [None] * n
976
977 # Do one loop nest at time recursively, until the # of loop nests
978 # remaining is divisible by 3.
979
980 def gen(i, values=values):
981 if i >= n:
982 yield values
983
984 elif (n-i) % 3:
985 ip1 = i+1
986 for values[i] in gs[i]():
987 for x in gen(ip1):
988 yield x
989
990 else:
991 for x in _gen3(i):
992 yield x
993
994 # Do three loop nests at a time, recursing only if at least three more
995 # remain. Don't call directly: this is an internal optimization for
996 # gen's use.
997
998 def _gen3(i, values=values):
999 assert i < n and (n-i) % 3 == 0
1000 ip1, ip2, ip3 = i+1, i+2, i+3
1001 g, g1, g2 = gs[i : ip3]
1002
1003 if ip3 >= n:
1004 # These are the last three, so we can yield values directly.
1005 for values[i] in g():
1006 for values[ip1] in g1():
1007 for values[ip2] in g2():
1008 yield values
1009
1010 else:
1011 # At least 6 loop nests remain; peel off 3 and recurse for the
1012 # rest.
1013 for values[i] in g():
1014 for values[ip1] in g1():
1015 for values[ip2] in g2():
1016 for x in _gen3(ip3):
1017 yield x
1018
1019 for x in gen(0):
1020 yield x
1021
unknown31569562001-07-04 22:11:22 +00001022# And one more approach: For backtracking apps like the Knight's Tour
1023# solver below, the number of backtracking levels can be enormous (one
1024# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1025# needs 10,000 levels). In such cases Python is likely to run out of
1026# stack space due to recursion. So here's a recursion-free version of
1027# conjoin too.
1028# NOTE WELL: This allows large problems to be solved with only trivial
1029# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001030# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1031# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001032
1033def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1034 n = len(gs)
1035 values = [None] * n
1036 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001037 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001038 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001039 while 1:
1040 # Descend.
1041 try:
1042 while i < n:
1043 it = iters[i] = gs[i]().next
1044 values[i] = it()
1045 i += 1
1046 except _StopIteration:
1047 pass
unknown31569562001-07-04 22:11:22 +00001048 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001049 assert i == n
1050 yield values
unknown31569562001-07-04 22:11:22 +00001051
Tim Peters9a8c8e22001-07-13 09:12:12 +00001052 # Backtrack until an older iterator can be resumed.
1053 i -= 1
unknown31569562001-07-04 22:11:22 +00001054 while i >= 0:
1055 try:
1056 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001057 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001058 i += 1
1059 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001060 except _StopIteration:
1061 # Continue backtracking.
1062 i -= 1
1063 else:
1064 assert i < 0
1065 break
unknown31569562001-07-04 22:11:22 +00001066
Tim Petersbe4f0a72001-06-29 02:41:16 +00001067# A conjoin-based N-Queens solver.
1068
1069class Queens:
1070 def __init__(self, n):
1071 self.n = n
1072 rangen = range(n)
1073
1074 # Assign a unique int to each column and diagonal.
1075 # columns: n of those, range(n).
1076 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1077 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1078 # based.
1079 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1080 # each, smallest i+j is 0, largest is 2n-2.
1081
1082 # For each square, compute a bit vector of the columns and
1083 # diagonals it covers, and for each row compute a function that
1084 # generates the possiblities for the columns in that row.
1085 self.rowgenerators = []
1086 for i in rangen:
1087 rowuses = [(1L << j) | # column ordinal
1088 (1L << (n + i-j + n-1)) | # NW-SE ordinal
1089 (1L << (n + 2*n-1 + i+j)) # NE-SW ordinal
1090 for j in rangen]
1091
1092 def rowgen(rowuses=rowuses):
1093 for j in rangen:
1094 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001095 if uses & self.used == 0:
1096 self.used |= uses
1097 yield j
1098 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001099
1100 self.rowgenerators.append(rowgen)
1101
1102 # Generate solutions.
1103 def solve(self):
1104 self.used = 0
1105 for row2col in conjoin(self.rowgenerators):
1106 yield row2col
1107
1108 def printsolution(self, row2col):
1109 n = self.n
1110 assert n == len(row2col)
1111 sep = "+" + "-+" * n
1112 print sep
1113 for i in range(n):
1114 squares = [" " for j in range(n)]
1115 squares[row2col[i]] = "Q"
1116 print "|" + "|".join(squares) + "|"
1117 print sep
1118
unknown31569562001-07-04 22:11:22 +00001119# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1120# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1121# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001122# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001123
1124class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001125 def __init__(self, m, n, hard=0):
1126 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001127
Tim Peters9a8c8e22001-07-13 09:12:12 +00001128 # solve() will set up succs[i] to be a list of square #i's
1129 # successors.
1130 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001131
Tim Peters9a8c8e22001-07-13 09:12:12 +00001132 # Remove i0 from each of its successor's successor lists, i.e.
1133 # successors can't go back to i0 again. Return 0 if we can
1134 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001135
Tim Peters9a8c8e22001-07-13 09:12:12 +00001136 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001137 # If we remove all exits from a free square, we're dead:
1138 # even if we move to it next, we can't leave it again.
1139 # If we create a square with one exit, we must visit it next;
1140 # else somebody else will have to visit it, and since there's
1141 # only one adjacent, there won't be a way to leave it again.
1142 # Finelly, if we create more than one free square with a
1143 # single exit, we can only move to one of them next, leaving
1144 # the other one a dead end.
1145 ne0 = ne1 = 0
1146 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001147 s = succs[i]
1148 s.remove(i0)
1149 e = len(s)
1150 if e == 0:
1151 ne0 += 1
1152 elif e == 1:
1153 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001154 return ne0 == 0 and ne1 < 2
1155
Tim Peters9a8c8e22001-07-13 09:12:12 +00001156 # Put i0 back in each of its successor's successor lists.
1157
1158 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001159 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001160 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001161
1162 # Generate the first move.
1163 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001164 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001165 return
1166
unknown31569562001-07-04 22:11:22 +00001167 # Since we're looking for a cycle, it doesn't matter where we
1168 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001169 corner = self.coords2index(0, 0)
1170 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001171 self.lastij = corner
1172 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001173 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001174
1175 # Generate the second moves.
1176 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001177 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001178 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001179 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001180 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001181 assert len(succs[corner]) == 2
1182 assert self.coords2index(1, 2) in succs[corner]
1183 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001184 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001185 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001186 # to (0, 0). Save its index in self.final so that moves before
1187 # the last know it must be kept free.
1188 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001189 this = self.coords2index(i, j)
1190 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001191 self.final = final
unknown31569562001-07-04 22:11:22 +00001192
Tim Peters9a8c8e22001-07-13 09:12:12 +00001193 remove_from_successors(this)
1194 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001195 self.lastij = this
1196 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 succs[final].remove(corner)
1198 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001199
Tim Peters9a8c8e22001-07-13 09:12:12 +00001200 # Generate moves 3 thru m*n-1.
1201 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001202 # If some successor has only one exit, must take it.
1203 # Else favor successors with fewer exits.
1204 candidates = []
1205 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001206 e = len(succs[i])
1207 assert e > 0, "else remove_from_successors() pruning flawed"
1208 if e == 1:
1209 candidates = [(e, i)]
1210 break
1211 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001212 else:
1213 candidates.sort()
1214
1215 for e, i in candidates:
1216 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001217 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001218 self.lastij = i
1219 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001220 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001221
Tim Peters9a8c8e22001-07-13 09:12:12 +00001222 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001223 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001224 # Since the # of backtracking levels is m*n, a poor move early on
1225 # can take eons to undo. Smallest square board for which this
1226 # matters a lot is 52x52.
1227 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001228 # If some successor has only one exit, must take it.
1229 # Else favor successors with fewer exits.
1230 # Break ties via max distance from board centerpoint (favor
1231 # corners and edges whenever possible).
1232 candidates = []
1233 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001234 e = len(succs[i])
1235 assert e > 0, "else remove_from_successors() pruning flawed"
1236 if e == 1:
1237 candidates = [(e, 0, i)]
1238 break
1239 i1, j1 = self.index2coords(i)
1240 d = (i1 - vmid)**2 + (j1 - hmid)**2
1241 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001242 else:
1243 candidates.sort()
1244
1245 for e, d, i in candidates:
1246 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001247 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001248 self.lastij = i
1249 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001250 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001251
1252 # Generate the last move.
1253 def last():
1254 assert self.final in succs[self.lastij]
1255 yield self.final
1256
Tim Peters9a8c8e22001-07-13 09:12:12 +00001257 if m*n < 4:
1258 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001259 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001260 self.squaregenerators = [first, second] + \
1261 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001262 [last]
1263
Tim Peters9a8c8e22001-07-13 09:12:12 +00001264 def coords2index(self, i, j):
1265 assert 0 <= i < self.m
1266 assert 0 <= j < self.n
1267 return i * self.n + j
1268
1269 def index2coords(self, index):
1270 assert 0 <= index < self.m * self.n
1271 return divmod(index, self.n)
1272
1273 def _init_board(self):
1274 succs = self.succs
1275 del succs[:]
1276 m, n = self.m, self.n
1277 c2i = self.coords2index
1278
1279 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1280 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1281 rangen = range(n)
1282 for i in range(m):
1283 for j in rangen:
1284 s = [c2i(i+io, j+jo) for io, jo in offsets
1285 if 0 <= i+io < m and
1286 0 <= j+jo < n]
1287 succs.append(s)
1288
unknown31569562001-07-04 22:11:22 +00001289 # Generate solutions.
1290 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001291 self._init_board()
1292 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001293 yield x
1294
1295 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001296 m, n = self.m, self.n
1297 assert len(x) == m*n
1298 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001299 format = "%" + str(w) + "d"
1300
Tim Peters9a8c8e22001-07-13 09:12:12 +00001301 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001302 k = 1
1303 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001304 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001305 squares[i1][j1] = format % k
1306 k += 1
1307
1308 sep = "+" + ("-" * w + "+") * n
1309 print sep
Tim Peters9a8c8e22001-07-13 09:12:12 +00001310 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001311 row = squares[i]
1312 print "|" + "|".join(row) + "|"
1313 print sep
1314
Tim Petersbe4f0a72001-06-29 02:41:16 +00001315conjoin_tests = """
1316
1317Generate the 3-bit binary numbers in order. This illustrates dumbest-
1318possible use of conjoin, just to generate the full cross-product.
1319
unknown31569562001-07-04 22:11:22 +00001320>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001321... print c
1322[0, 0, 0]
1323[0, 0, 1]
1324[0, 1, 0]
1325[0, 1, 1]
1326[1, 0, 0]
1327[1, 0, 1]
1328[1, 1, 0]
1329[1, 1, 1]
1330
Tim Petersc468fd22001-06-30 07:29:44 +00001331For efficiency in typical backtracking apps, conjoin() yields the same list
1332object each time. So if you want to save away a full account of its
1333generated sequence, you need to copy its results.
1334
1335>>> def gencopy(iterator):
1336... for x in iterator:
1337... yield x[:]
1338
1339>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001340... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Tim Petersc468fd22001-06-30 07:29:44 +00001341... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n
Guido van Rossum77f6a652002-04-03 22:41:51 +000013420 1 True True
13431 2 True True
13442 4 True True
13453 8 True True
13464 16 True True
13475 32 True True
13486 64 True True
13497 128 True True
13508 256 True True
13519 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001352
Tim Petersbe4f0a72001-06-29 02:41:16 +00001353And run an 8-queens solver.
1354
1355>>> q = Queens(8)
1356>>> LIMIT = 2
1357>>> count = 0
1358>>> for row2col in q.solve():
1359... count += 1
1360... if count <= LIMIT:
1361... print "Solution", count
1362... q.printsolution(row2col)
1363Solution 1
1364+-+-+-+-+-+-+-+-+
1365|Q| | | | | | | |
1366+-+-+-+-+-+-+-+-+
1367| | | | |Q| | | |
1368+-+-+-+-+-+-+-+-+
1369| | | | | | | |Q|
1370+-+-+-+-+-+-+-+-+
1371| | | | | |Q| | |
1372+-+-+-+-+-+-+-+-+
1373| | |Q| | | | | |
1374+-+-+-+-+-+-+-+-+
1375| | | | | | |Q| |
1376+-+-+-+-+-+-+-+-+
1377| |Q| | | | | | |
1378+-+-+-+-+-+-+-+-+
1379| | | |Q| | | | |
1380+-+-+-+-+-+-+-+-+
1381Solution 2
1382+-+-+-+-+-+-+-+-+
1383|Q| | | | | | | |
1384+-+-+-+-+-+-+-+-+
1385| | | | | |Q| | |
1386+-+-+-+-+-+-+-+-+
1387| | | | | | | |Q|
1388+-+-+-+-+-+-+-+-+
1389| | |Q| | | | | |
1390+-+-+-+-+-+-+-+-+
1391| | | | | | |Q| |
1392+-+-+-+-+-+-+-+-+
1393| | | |Q| | | | |
1394+-+-+-+-+-+-+-+-+
1395| |Q| | | | | | |
1396+-+-+-+-+-+-+-+-+
1397| | | | |Q| | | |
1398+-+-+-+-+-+-+-+-+
1399
1400>>> print count, "solutions in all."
140192 solutions in all.
unknown31569562001-07-04 22:11:22 +00001402
1403And run a Knight's Tour on a 10x10 board. Note that there are about
140420,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1405
Tim Peters9a8c8e22001-07-13 09:12:12 +00001406>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001407>>> LIMIT = 2
1408>>> count = 0
1409>>> for x in k.solve():
1410... count += 1
1411... if count <= LIMIT:
1412... print "Solution", count
1413... k.printsolution(x)
1414... else:
1415... break
1416Solution 1
1417+---+---+---+---+---+---+---+---+---+---+
1418| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1419+---+---+---+---+---+---+---+---+---+---+
1420| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1421+---+---+---+---+---+---+---+---+---+---+
1422| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1423+---+---+---+---+---+---+---+---+---+---+
1424| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1425+---+---+---+---+---+---+---+---+---+---+
1426| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1427+---+---+---+---+---+---+---+---+---+---+
1428| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1429+---+---+---+---+---+---+---+---+---+---+
1430| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1431+---+---+---+---+---+---+---+---+---+---+
1432| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1433+---+---+---+---+---+---+---+---+---+---+
1434| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1435+---+---+---+---+---+---+---+---+---+---+
1436| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1437+---+---+---+---+---+---+---+---+---+---+
1438Solution 2
1439+---+---+---+---+---+---+---+---+---+---+
1440| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1441+---+---+---+---+---+---+---+---+---+---+
1442| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1443+---+---+---+---+---+---+---+---+---+---+
1444| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1445+---+---+---+---+---+---+---+---+---+---+
1446| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1447+---+---+---+---+---+---+---+---+---+---+
1448| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1449+---+---+---+---+---+---+---+---+---+---+
1450| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1451+---+---+---+---+---+---+---+---+---+---+
1452| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1453+---+---+---+---+---+---+---+---+---+---+
1454| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1455+---+---+---+---+---+---+---+---+---+---+
1456| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1457+---+---+---+---+---+---+---+---+---+---+
1458| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1459+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001460"""
1461
Fred Drake56d12662002-08-09 18:37:10 +00001462weakref_tests = """\
1463Generators are weakly referencable:
1464
1465>>> import weakref
1466>>> def gen():
1467... yield 'foo!'
1468...
1469>>> wr = weakref.ref(gen)
1470>>> wr() is gen
1471True
1472>>> p = weakref.proxy(gen)
1473
1474Generator-iterators are weakly referencable as well:
1475
1476>>> gi = gen()
1477>>> wr = weakref.ref(gi)
1478>>> wr() is gi
1479True
1480>>> p = weakref.proxy(gi)
1481>>> list(p)
1482['foo!']
1483
1484"""
1485
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001486coroutine_tests = """\
1487Sending a value into a started generator:
1488
1489>>> def f():
1490... print (yield 1)
1491... yield 2
1492>>> g = f()
1493>>> g.next()
14941
1495>>> g.send(42)
149642
14972
1498
1499Sending a value into a new generator produces a TypeError:
1500
1501>>> f().send("foo")
1502Traceback (most recent call last):
1503...
1504TypeError: can't send non-None value to a just-started generator
1505
1506
1507Yield by itself yields None:
1508
1509>>> def f(): yield
1510>>> list(f())
1511[None]
1512
1513
1514
1515An obscene abuse of a yield expression within a generator expression:
1516
1517>>> list((yield 21) for i in range(4))
1518[21, None, 21, None, 21, None, 21, None]
1519
1520And a more sane, but still weird usage:
1521
1522>>> def f(): list(i for i in [(yield 26)])
1523>>> type(f())
1524<type 'generator'>
1525
1526
1527Check some syntax errors for yield expressions:
1528
1529>>> f=lambda: (yield 1),(yield 2)
1530Traceback (most recent call last):
1531 ...
1532SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[10]>, line 1)
1533
1534>>> def f(): return lambda x=(yield): 1
1535Traceback (most recent call last):
1536 ...
1537SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[11]>, line 1)
1538
1539>>> def f(): x = yield = y
1540Traceback (most recent call last):
1541 ...
1542SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[12]>, line 1)
1543
1544
1545Now check some throw() conditions:
1546
1547>>> def f():
1548... while True:
1549... try:
1550... print (yield)
1551... except ValueError,v:
1552... print "caught ValueError (%s)" % (v),
1553>>> import sys
1554>>> g = f()
1555>>> g.next()
1556
1557>>> g.throw(ValueError) # type only
1558caught ValueError ()
1559
1560>>> g.throw(ValueError("xyz")) # value only
1561caught ValueError (xyz)
1562
1563>>> g.throw(ValueError, ValueError(1)) # value+matching type
1564caught ValueError (1)
1565
1566>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1567caught ValueError (1)
1568
Phillip J. Ebybee07122006-03-25 00:05:50 +00001569>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1570caught ValueError (1)
1571
Tim Peterse9fe7e02005-08-07 03:04:58 +00001572>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001573Traceback (most recent call last):
1574 ...
1575TypeError: instance exception may not have a separate value
1576
Tim Peterse9fe7e02005-08-07 03:04:58 +00001577>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001578Traceback (most recent call last):
1579 ...
1580TypeError: throw() third argument must be a traceback object
1581
1582>>> def throw(g,exc):
1583... try:
1584... raise exc
1585... except:
1586... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001587>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001588caught ValueError ()
1589
1590>>> g.send(1)
15911
1592
Tim Peterse9fe7e02005-08-07 03:04:58 +00001593>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001594Traceback (most recent call last):
1595 ...
1596TypeError
1597
1598>>> print g.gi_frame
1599None
1600
1601>>> g.send(2)
1602Traceback (most recent call last):
1603 ...
1604StopIteration
1605
Tim Peterse9fe7e02005-08-07 03:04:58 +00001606>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001607Traceback (most recent call last):
1608 ...
1609ValueError: 6
1610
Tim Peterse9fe7e02005-08-07 03:04:58 +00001611>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001612Traceback (most recent call last):
1613 ...
1614ValueError: 7
1615
Neal Norwitzfcf44352005-11-27 20:37:43 +00001616>>> f().throw("abc") # throw on just-opened generator
1617Traceback (most recent call last):
1618 ...
Phillip J. Ebybee07122006-03-25 00:05:50 +00001619abc
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001620
1621Now let's try closing a generator:
1622
1623>>> def f():
1624... try: yield
1625... except GeneratorExit:
1626... print "exiting"
1627
1628>>> g = f()
1629>>> g.next()
1630>>> g.close()
1631exiting
1632>>> g.close() # should be no-op now
1633
1634>>> f().close() # close on just-opened generator should be fine
1635
Tim Peterse9fe7e02005-08-07 03:04:58 +00001636>>> def f(): yield # an even simpler generator
1637>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001638>>> g = f()
1639>>> g.next()
Tim Peterse9fe7e02005-08-07 03:04:58 +00001640>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001641
1642And finalization:
1643
1644>>> def f():
1645... try: yield
1646... finally:
1647... print "exiting"
1648
1649>>> g = f()
1650>>> g.next()
1651>>> del g
1652exiting
1653
1654
1655Now let's try some ill-behaved generators:
1656
1657>>> def f():
1658... try: yield
1659... except GeneratorExit:
1660... yield "foo!"
1661>>> g = f()
1662>>> g.next()
1663>>> g.close()
1664Traceback (most recent call last):
1665 ...
1666RuntimeError: generator ignored GeneratorExit
1667>>> g.close()
1668
1669
1670Our ill-behaved code should be invoked during GC:
1671
1672>>> import sys, StringIO
1673>>> old, sys.stderr = sys.stderr, StringIO.StringIO()
1674>>> g = f()
1675>>> g.next()
1676>>> del g
1677>>> sys.stderr.getvalue().startswith(
1678... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in "
1679... )
1680True
1681>>> sys.stderr = old
1682
1683
1684And errors thrown during closing should propagate:
1685
1686>>> def f():
1687... try: yield
1688... except GeneratorExit:
1689... raise TypeError("fie!")
1690>>> g = f()
1691>>> g.next()
1692>>> g.close()
1693Traceback (most recent call last):
1694 ...
1695TypeError: fie!
1696
1697
1698Ensure that various yield expression constructs make their
1699enclosing function a generator:
1700
1701>>> def f(): x += yield
1702>>> type(f())
1703<type 'generator'>
1704
1705>>> def f(): x = yield
1706>>> type(f())
1707<type 'generator'>
1708
1709>>> def f(): lambda x=(yield): 1
1710>>> type(f())
1711<type 'generator'>
1712
1713>>> def f(): x=(i for i in (yield) if (yield))
1714>>> type(f())
1715<type 'generator'>
1716
1717>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1718>>> data = [1,2]
1719>>> g = f(data)
1720>>> type(g)
1721<type 'generator'>
1722>>> g.send(None)
1723'a'
1724>>> data
1725[1, 2]
1726>>> g.send(0)
1727'b'
1728>>> data
1729[27, 2]
1730>>> try: g.send(1)
1731... except StopIteration: pass
1732>>> data
1733[27, 27]
1734
1735"""
1736
Thomas Wouters4054b972006-03-28 08:44:55 +00001737refleaks_tests = """
1738Prior to adding cycle-GC support to itertools.tee, this code would leak
1739references. We add it to the standard suite so the routine refleak-tests
1740would trigger if it starts being uncleanable again.
1741
1742>>> import itertools
1743>>> def leak():
1744... class gen:
1745... def __iter__(self):
1746... return self
1747... def next(self):
1748... return self.item
1749... g = gen()
1750... head, tail = itertools.tee(g)
1751... g.item = head
1752... return head
1753>>> it = leak()
1754
1755Make sure to also test the involvement of the tee-internal teedataobject,
1756which stores returned items.
1757
1758>>> item = it.next()
1759
1760There should be more test_generator-induced refleaks here, after they get
1761fixed.
1762
1763"""
1764
Tim Petersf6ed0742001-06-27 07:17:57 +00001765__test__ = {"tut": tutorial_tests,
1766 "pep": pep_tests,
1767 "email": email_tests,
1768 "fun": fun_tests,
Neal Norwitzcde87502006-04-14 06:11:08 +00001769 "leak1": leak_test1,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001770 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001771 "conjoin": conjoin_tests,
1772 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001773 "coroutine": coroutine_tests,
Thomas Wouters4054b972006-03-28 08:44:55 +00001774 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001775 }
Tim Peters1def3512001-06-23 20:27:04 +00001776
1777# Magic test name that regrtest.py invokes *after* importing this module.
1778# This worms around a bootstrap problem.
1779# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1780# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001781def test_main(verbose=None):
Barry Warsaw04f357c2002-07-23 19:04:11 +00001782 from test import test_support, test_generators
Tim Peterscca01832004-08-27 15:29:59 +00001783 test_support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001784
1785# This part isn't needed for regrtest, but for running the test directly.
1786if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001787 test_main(1)