blob: ee36413de7ccd4f733f1bf9c7959c049b186605e [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 Woutersb3deb942006-04-15 22:33:13 +0000671m235 to share a single generator".
Georg Brandl52715f62005-08-24 09:02:29 +0000672
673>>> from itertools import tee
674>>> def m235():
675... def _m235():
676... yield 1
677... for n in merge(times(2, m2),
678... merge(times(3, m3),
679... times(5, m5))):
680... yield n
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000681... m1 = _m235()
682... m2, m3, m5, mRes = tee(m1, 4)
Thomas Woutersb3deb942006-04-15 22:33:13 +0000683... return mRes
Georg Brandl52715f62005-08-24 09:02:29 +0000684
Thomas Woutersb3deb942006-04-15 22:33:13 +0000685>>> it = m235()
Georg Brandl52715f62005-08-24 09:02:29 +0000686>>> for i in range(5):
687... print firstn(it, 15)
688[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
689[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
690[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
691[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
692[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
693
694The "tee" function does just what we want. It internally keeps a generated
695result for as long as it has not been "consumed" from all of the duplicated
696iterators, whereupon it is deleted. You can therefore print the hamming
697sequence during hours without increasing memory usage, or very little.
698
Tim Peters7f098112006-04-15 01:48:57 +0000699The beauty of it is that recursive running-after-their-tail FP algorithms
Thomas Woutersb3deb942006-04-15 22:33:13 +0000700are quite straightforwardly expressed with this Python idiom.
Georg Brandl52715f62005-08-24 09:02:29 +0000701
702Ye olde Fibonacci generator, tee style.
703
704>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +0000705...
Georg Brandl52715f62005-08-24 09:02:29 +0000706... def _isum(g, h):
707... while 1:
708... yield g.next() + h.next()
Tim Peters9e34c042005-08-26 15:20:46 +0000709...
Georg Brandl52715f62005-08-24 09:02:29 +0000710... def _fib():
711... yield 1
712... yield 2
713... fibTail.next() # throw first away
714... for res in _isum(fibHead, fibTail):
715... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000716...
Thomas Woutersa6126ba2006-03-31 15:31:43 +0000717... realfib = _fib()
718... fibHead, fibTail, fibRes = tee(realfib, 3)
Thomas Woutersb3deb942006-04-15 22:33:13 +0000719... return fibRes
Georg Brandl52715f62005-08-24 09:02:29 +0000720
Thomas Woutersb3deb942006-04-15 22:33:13 +0000721>>> firstn(fib(), 17)
Georg Brandl52715f62005-08-24 09:02:29 +0000722[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
723
Tim Peters0f9da0a2001-06-23 21:01:47 +0000724"""
725
Tim Petersb6c3cea2001-06-26 03:36:28 +0000726# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
727# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000728
Tim Petersea2e97a2001-06-24 07:10:02 +0000729syntax_tests = """
730
Tim Petersaef8cfa2004-08-27 15:12:49 +0000731>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000732... return 22
733... yield 1
734Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000735 ..
Georg Brandlddbaa662006-06-04 21:56:52 +0000736SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000737
Tim Petersaef8cfa2004-08-27 15:12:49 +0000738>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000739... yield 1
740... return 22
741Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000742 ..
Tim Petersc5684782004-09-13 01:07:12 +0000743SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000744
745"return None" is not the same as "return" in a generator:
746
Tim Petersaef8cfa2004-08-27 15:12:49 +0000747>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000748... yield 1
749... return None
750Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000751 ..
Tim Petersc5684782004-09-13 01:07:12 +0000752SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000753
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000754These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000755
756>>> def f():
757... yield 1
758... return
759
Tim Petersaef8cfa2004-08-27 15:12:49 +0000760>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000761... try:
762... yield 1
763... finally:
764... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000765
Tim Petersaef8cfa2004-08-27 15:12:49 +0000766>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000767... try:
768... try:
Tim Peters3caca232001-12-06 06:23:26 +0000769... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000770... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000771... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000772... except:
773... pass
774... finally:
775... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000776
777>>> def f():
778... try:
779... try:
780... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000781... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000782... except ZeroDivisionError:
783... yield 666
784... except:
785... try:
786... x = 12
787... finally:
788... yield 12
789... except:
790... return
791>>> list(f())
792[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000793
794>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000795... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000796>>> type(f())
797<type 'generator'>
798
Tim Peters08a898f2001-06-28 01:52:22 +0000799
800>>> def f():
801... if 0:
802... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000803>>> type(f())
804<type 'generator'>
805
Tim Peters08a898f2001-06-28 01:52:22 +0000806
807>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000808... if 0:
809... yield 1
810>>> type(f())
811<type 'generator'>
812
813>>> def f():
814... if "":
815... yield None
816>>> type(f())
817<type 'generator'>
818
819>>> def f():
820... return
821... try:
822... if x==4:
823... pass
824... elif 0:
825... try:
Tim Peters3caca232001-12-06 06:23:26 +0000826... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000827... except SyntaxError:
828... pass
829... else:
830... if 0:
831... while 12:
832... x += 1
833... yield 2 # don't blink
834... f(a, b, c, d, e)
835... else:
836... pass
837... except:
838... x = 1
839... return
840>>> type(f())
841<type 'generator'>
842
843>>> def f():
844... if 0:
845... def g():
846... yield 1
847...
848>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000849<type 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000850
851>>> def f():
852... if 0:
853... class C:
854... def __init__(self):
855... yield 1
856... def f(self):
857... yield 2
858>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000859<type 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000860
861>>> def f():
862... if 0:
863... return
864... if 0:
865... yield 2
866>>> type(f())
867<type 'generator'>
868
869
Tim Petersaef8cfa2004-08-27 15:12:49 +0000870>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000871... if 0:
872... lambda x: x # shouldn't trigger here
873... return # or here
874... def f(i):
875... return 2*i # or here
876... if 0:
877... return 3 # but *this* sucks (line 8)
878... if 0:
Georg Brandlddbaa662006-06-04 21:56:52 +0000879... yield 2 # because it's a generator (line 10)
Tim Peters08a898f2001-06-28 01:52:22 +0000880Traceback (most recent call last):
Georg Brandlddbaa662006-06-04 21:56:52 +0000881SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 10)
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000882
883This one caused a crash (see SF bug 567538):
884
885>>> def f():
886... for i in range(3):
887... try:
888... continue
889... finally:
890... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000891...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000892>>> g = f()
893>>> print g.next()
8940
895>>> print g.next()
8961
897>>> print g.next()
8982
899>>> print g.next()
900Traceback (most recent call last):
901StopIteration
Tim Petersea2e97a2001-06-24 07:10:02 +0000902"""
903
Tim Petersbe4f0a72001-06-29 02:41:16 +0000904# conjoin is a simple backtracking generator, named in honor of Icon's
905# "conjunction" control structure. Pass a list of no-argument functions
906# that return iterable objects. Easiest to explain by example: assume the
907# function list [x, y, z] is passed. Then conjoin acts like:
908#
909# def g():
910# values = [None] * 3
911# for values[0] in x():
912# for values[1] in y():
913# for values[2] in z():
914# yield values
915#
916# So some 3-lists of values *may* be generated, each time we successfully
917# get into the innermost loop. If an iterator fails (is exhausted) before
918# then, it "backtracks" to get the next value from the nearest enclosing
919# iterator (the one "to the left"), and starts all over again at the next
920# slot (pumps a fresh iterator). Of course this is most useful when the
921# iterators have side-effects, so that which values *can* be generated at
922# each slot depend on the values iterated at previous slots.
923
924def conjoin(gs):
925
926 values = [None] * len(gs)
927
928 def gen(i, values=values):
929 if i >= len(gs):
930 yield values
931 else:
932 for values[i] in gs[i]():
933 for x in gen(i+1):
934 yield x
935
936 for x in gen(0):
937 yield x
938
Tim Petersc468fd22001-06-30 07:29:44 +0000939# That works fine, but recursing a level and checking i against len(gs) for
940# each item produced is inefficient. By doing manual loop unrolling across
941# generator boundaries, it's possible to eliminate most of that overhead.
942# This isn't worth the bother *in general* for generators, but conjoin() is
943# a core building block for some CPU-intensive generator applications.
944
945def conjoin(gs):
946
947 n = len(gs)
948 values = [None] * n
949
950 # Do one loop nest at time recursively, until the # of loop nests
951 # remaining is divisible by 3.
952
953 def gen(i, values=values):
954 if i >= n:
955 yield values
956
957 elif (n-i) % 3:
958 ip1 = i+1
959 for values[i] in gs[i]():
960 for x in gen(ip1):
961 yield x
962
963 else:
964 for x in _gen3(i):
965 yield x
966
967 # Do three loop nests at a time, recursing only if at least three more
968 # remain. Don't call directly: this is an internal optimization for
969 # gen's use.
970
971 def _gen3(i, values=values):
972 assert i < n and (n-i) % 3 == 0
973 ip1, ip2, ip3 = i+1, i+2, i+3
974 g, g1, g2 = gs[i : ip3]
975
976 if ip3 >= n:
977 # These are the last three, so we can yield values directly.
978 for values[i] in g():
979 for values[ip1] in g1():
980 for values[ip2] in g2():
981 yield values
982
983 else:
984 # At least 6 loop nests remain; peel off 3 and recurse for the
985 # rest.
986 for values[i] in g():
987 for values[ip1] in g1():
988 for values[ip2] in g2():
989 for x in _gen3(ip3):
990 yield x
991
992 for x in gen(0):
993 yield x
994
unknown31569562001-07-04 22:11:22 +0000995# And one more approach: For backtracking apps like the Knight's Tour
996# solver below, the number of backtracking levels can be enormous (one
997# level per square, for the Knight's Tour, so that e.g. a 100x100 board
998# needs 10,000 levels). In such cases Python is likely to run out of
999# stack space due to recursion. So here's a recursion-free version of
1000# conjoin too.
1001# NOTE WELL: This allows large problems to be solved with only trivial
1002# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001003# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1004# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001005
1006def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1007 n = len(gs)
1008 values = [None] * n
1009 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001010 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001011 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001012 while 1:
1013 # Descend.
1014 try:
1015 while i < n:
1016 it = iters[i] = gs[i]().next
1017 values[i] = it()
1018 i += 1
1019 except _StopIteration:
1020 pass
unknown31569562001-07-04 22:11:22 +00001021 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001022 assert i == n
1023 yield values
unknown31569562001-07-04 22:11:22 +00001024
Tim Peters9a8c8e22001-07-13 09:12:12 +00001025 # Backtrack until an older iterator can be resumed.
1026 i -= 1
unknown31569562001-07-04 22:11:22 +00001027 while i >= 0:
1028 try:
1029 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001030 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001031 i += 1
1032 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001033 except _StopIteration:
1034 # Continue backtracking.
1035 i -= 1
1036 else:
1037 assert i < 0
1038 break
unknown31569562001-07-04 22:11:22 +00001039
Tim Petersbe4f0a72001-06-29 02:41:16 +00001040# A conjoin-based N-Queens solver.
1041
1042class Queens:
1043 def __init__(self, n):
1044 self.n = n
1045 rangen = range(n)
1046
1047 # Assign a unique int to each column and diagonal.
1048 # columns: n of those, range(n).
1049 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1050 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1051 # based.
1052 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1053 # each, smallest i+j is 0, largest is 2n-2.
1054
1055 # For each square, compute a bit vector of the columns and
1056 # diagonals it covers, and for each row compute a function that
1057 # generates the possiblities for the columns in that row.
1058 self.rowgenerators = []
1059 for i in rangen:
1060 rowuses = [(1L << j) | # column ordinal
1061 (1L << (n + i-j + n-1)) | # NW-SE ordinal
1062 (1L << (n + 2*n-1 + i+j)) # NE-SW ordinal
1063 for j in rangen]
1064
1065 def rowgen(rowuses=rowuses):
1066 for j in rangen:
1067 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001068 if uses & self.used == 0:
1069 self.used |= uses
1070 yield j
1071 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001072
1073 self.rowgenerators.append(rowgen)
1074
1075 # Generate solutions.
1076 def solve(self):
1077 self.used = 0
1078 for row2col in conjoin(self.rowgenerators):
1079 yield row2col
1080
1081 def printsolution(self, row2col):
1082 n = self.n
1083 assert n == len(row2col)
1084 sep = "+" + "-+" * n
1085 print sep
1086 for i in range(n):
1087 squares = [" " for j in range(n)]
1088 squares[row2col[i]] = "Q"
1089 print "|" + "|".join(squares) + "|"
1090 print sep
1091
unknown31569562001-07-04 22:11:22 +00001092# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1093# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1094# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001095# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001096
1097class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001098 def __init__(self, m, n, hard=0):
1099 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001100
Tim Peters9a8c8e22001-07-13 09:12:12 +00001101 # solve() will set up succs[i] to be a list of square #i's
1102 # successors.
1103 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001104
Tim Peters9a8c8e22001-07-13 09:12:12 +00001105 # Remove i0 from each of its successor's successor lists, i.e.
1106 # successors can't go back to i0 again. Return 0 if we can
1107 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001108
Tim Peters9a8c8e22001-07-13 09:12:12 +00001109 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001110 # If we remove all exits from a free square, we're dead:
1111 # even if we move to it next, we can't leave it again.
1112 # If we create a square with one exit, we must visit it next;
1113 # else somebody else will have to visit it, and since there's
1114 # only one adjacent, there won't be a way to leave it again.
1115 # Finelly, if we create more than one free square with a
1116 # single exit, we can only move to one of them next, leaving
1117 # the other one a dead end.
1118 ne0 = ne1 = 0
1119 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001120 s = succs[i]
1121 s.remove(i0)
1122 e = len(s)
1123 if e == 0:
1124 ne0 += 1
1125 elif e == 1:
1126 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001127 return ne0 == 0 and ne1 < 2
1128
Tim Peters9a8c8e22001-07-13 09:12:12 +00001129 # Put i0 back in each of its successor's successor lists.
1130
1131 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001132 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001133 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001134
1135 # Generate the first move.
1136 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001137 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001138 return
1139
unknown31569562001-07-04 22:11:22 +00001140 # Since we're looking for a cycle, it doesn't matter where we
1141 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001142 corner = self.coords2index(0, 0)
1143 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001144 self.lastij = corner
1145 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001146 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001147
1148 # Generate the second moves.
1149 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001150 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001151 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001152 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001153 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001154 assert len(succs[corner]) == 2
1155 assert self.coords2index(1, 2) in succs[corner]
1156 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001157 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001158 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001159 # to (0, 0). Save its index in self.final so that moves before
1160 # the last know it must be kept free.
1161 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001162 this = self.coords2index(i, j)
1163 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001164 self.final = final
unknown31569562001-07-04 22:11:22 +00001165
Tim Peters9a8c8e22001-07-13 09:12:12 +00001166 remove_from_successors(this)
1167 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001168 self.lastij = this
1169 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001170 succs[final].remove(corner)
1171 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001172
Tim Peters9a8c8e22001-07-13 09:12:12 +00001173 # Generate moves 3 thru m*n-1.
1174 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001175 # If some successor has only one exit, must take it.
1176 # Else favor successors with fewer exits.
1177 candidates = []
1178 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001179 e = len(succs[i])
1180 assert e > 0, "else remove_from_successors() pruning flawed"
1181 if e == 1:
1182 candidates = [(e, i)]
1183 break
1184 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001185 else:
1186 candidates.sort()
1187
1188 for e, i in candidates:
1189 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001190 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001191 self.lastij = i
1192 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001193 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001194
Tim Peters9a8c8e22001-07-13 09:12:12 +00001195 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001196 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 # Since the # of backtracking levels is m*n, a poor move early on
1198 # can take eons to undo. Smallest square board for which this
1199 # matters a lot is 52x52.
1200 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001201 # If some successor has only one exit, must take it.
1202 # Else favor successors with fewer exits.
1203 # Break ties via max distance from board centerpoint (favor
1204 # corners and edges whenever possible).
1205 candidates = []
1206 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001207 e = len(succs[i])
1208 assert e > 0, "else remove_from_successors() pruning flawed"
1209 if e == 1:
1210 candidates = [(e, 0, i)]
1211 break
1212 i1, j1 = self.index2coords(i)
1213 d = (i1 - vmid)**2 + (j1 - hmid)**2
1214 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001215 else:
1216 candidates.sort()
1217
1218 for e, d, i in candidates:
1219 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001220 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001221 self.lastij = i
1222 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001223 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001224
1225 # Generate the last move.
1226 def last():
1227 assert self.final in succs[self.lastij]
1228 yield self.final
1229
Tim Peters9a8c8e22001-07-13 09:12:12 +00001230 if m*n < 4:
1231 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001232 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001233 self.squaregenerators = [first, second] + \
1234 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001235 [last]
1236
Tim Peters9a8c8e22001-07-13 09:12:12 +00001237 def coords2index(self, i, j):
1238 assert 0 <= i < self.m
1239 assert 0 <= j < self.n
1240 return i * self.n + j
1241
1242 def index2coords(self, index):
1243 assert 0 <= index < self.m * self.n
1244 return divmod(index, self.n)
1245
1246 def _init_board(self):
1247 succs = self.succs
1248 del succs[:]
1249 m, n = self.m, self.n
1250 c2i = self.coords2index
1251
1252 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1253 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1254 rangen = range(n)
1255 for i in range(m):
1256 for j in rangen:
1257 s = [c2i(i+io, j+jo) for io, jo in offsets
1258 if 0 <= i+io < m and
1259 0 <= j+jo < n]
1260 succs.append(s)
1261
unknown31569562001-07-04 22:11:22 +00001262 # Generate solutions.
1263 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001264 self._init_board()
1265 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001266 yield x
1267
1268 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001269 m, n = self.m, self.n
1270 assert len(x) == m*n
1271 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001272 format = "%" + str(w) + "d"
1273
Tim Peters9a8c8e22001-07-13 09:12:12 +00001274 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001275 k = 1
1276 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001277 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001278 squares[i1][j1] = format % k
1279 k += 1
1280
1281 sep = "+" + ("-" * w + "+") * n
1282 print sep
Tim Peters9a8c8e22001-07-13 09:12:12 +00001283 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001284 row = squares[i]
1285 print "|" + "|".join(row) + "|"
1286 print sep
1287
Tim Petersbe4f0a72001-06-29 02:41:16 +00001288conjoin_tests = """
1289
1290Generate the 3-bit binary numbers in order. This illustrates dumbest-
1291possible use of conjoin, just to generate the full cross-product.
1292
unknown31569562001-07-04 22:11:22 +00001293>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001294... print c
1295[0, 0, 0]
1296[0, 0, 1]
1297[0, 1, 0]
1298[0, 1, 1]
1299[1, 0, 0]
1300[1, 0, 1]
1301[1, 1, 0]
1302[1, 1, 1]
1303
Tim Petersc468fd22001-06-30 07:29:44 +00001304For efficiency in typical backtracking apps, conjoin() yields the same list
1305object each time. So if you want to save away a full account of its
1306generated sequence, you need to copy its results.
1307
1308>>> def gencopy(iterator):
1309... for x in iterator:
1310... yield x[:]
1311
1312>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001313... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Tim Petersc468fd22001-06-30 07:29:44 +00001314... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n
Guido van Rossum77f6a652002-04-03 22:41:51 +000013150 1 True True
13161 2 True True
13172 4 True True
13183 8 True True
13194 16 True True
13205 32 True True
13216 64 True True
13227 128 True True
13238 256 True True
13249 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001325
Tim Petersbe4f0a72001-06-29 02:41:16 +00001326And run an 8-queens solver.
1327
1328>>> q = Queens(8)
1329>>> LIMIT = 2
1330>>> count = 0
1331>>> for row2col in q.solve():
1332... count += 1
1333... if count <= LIMIT:
1334... print "Solution", count
1335... q.printsolution(row2col)
1336Solution 1
1337+-+-+-+-+-+-+-+-+
1338|Q| | | | | | | |
1339+-+-+-+-+-+-+-+-+
1340| | | | |Q| | | |
1341+-+-+-+-+-+-+-+-+
1342| | | | | | | |Q|
1343+-+-+-+-+-+-+-+-+
1344| | | | | |Q| | |
1345+-+-+-+-+-+-+-+-+
1346| | |Q| | | | | |
1347+-+-+-+-+-+-+-+-+
1348| | | | | | |Q| |
1349+-+-+-+-+-+-+-+-+
1350| |Q| | | | | | |
1351+-+-+-+-+-+-+-+-+
1352| | | |Q| | | | |
1353+-+-+-+-+-+-+-+-+
1354Solution 2
1355+-+-+-+-+-+-+-+-+
1356|Q| | | | | | | |
1357+-+-+-+-+-+-+-+-+
1358| | | | | |Q| | |
1359+-+-+-+-+-+-+-+-+
1360| | | | | | | |Q|
1361+-+-+-+-+-+-+-+-+
1362| | |Q| | | | | |
1363+-+-+-+-+-+-+-+-+
1364| | | | | | |Q| |
1365+-+-+-+-+-+-+-+-+
1366| | | |Q| | | | |
1367+-+-+-+-+-+-+-+-+
1368| |Q| | | | | | |
1369+-+-+-+-+-+-+-+-+
1370| | | | |Q| | | |
1371+-+-+-+-+-+-+-+-+
1372
1373>>> print count, "solutions in all."
137492 solutions in all.
unknown31569562001-07-04 22:11:22 +00001375
1376And run a Knight's Tour on a 10x10 board. Note that there are about
137720,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1378
Tim Peters9a8c8e22001-07-13 09:12:12 +00001379>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001380>>> LIMIT = 2
1381>>> count = 0
1382>>> for x in k.solve():
1383... count += 1
1384... if count <= LIMIT:
1385... print "Solution", count
1386... k.printsolution(x)
1387... else:
1388... break
1389Solution 1
1390+---+---+---+---+---+---+---+---+---+---+
1391| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1392+---+---+---+---+---+---+---+---+---+---+
1393| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1394+---+---+---+---+---+---+---+---+---+---+
1395| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1396+---+---+---+---+---+---+---+---+---+---+
1397| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1398+---+---+---+---+---+---+---+---+---+---+
1399| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1400+---+---+---+---+---+---+---+---+---+---+
1401| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1402+---+---+---+---+---+---+---+---+---+---+
1403| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1404+---+---+---+---+---+---+---+---+---+---+
1405| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1406+---+---+---+---+---+---+---+---+---+---+
1407| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1408+---+---+---+---+---+---+---+---+---+---+
1409| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1410+---+---+---+---+---+---+---+---+---+---+
1411Solution 2
1412+---+---+---+---+---+---+---+---+---+---+
1413| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1414+---+---+---+---+---+---+---+---+---+---+
1415| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1416+---+---+---+---+---+---+---+---+---+---+
1417| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1418+---+---+---+---+---+---+---+---+---+---+
1419| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1420+---+---+---+---+---+---+---+---+---+---+
1421| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1422+---+---+---+---+---+---+---+---+---+---+
1423| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1424+---+---+---+---+---+---+---+---+---+---+
1425| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1426+---+---+---+---+---+---+---+---+---+---+
1427| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1428+---+---+---+---+---+---+---+---+---+---+
1429| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1430+---+---+---+---+---+---+---+---+---+---+
1431| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1432+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001433"""
1434
Fred Drake56d12662002-08-09 18:37:10 +00001435weakref_tests = """\
1436Generators are weakly referencable:
1437
1438>>> import weakref
1439>>> def gen():
1440... yield 'foo!'
1441...
1442>>> wr = weakref.ref(gen)
1443>>> wr() is gen
1444True
1445>>> p = weakref.proxy(gen)
1446
1447Generator-iterators are weakly referencable as well:
1448
1449>>> gi = gen()
1450>>> wr = weakref.ref(gi)
1451>>> wr() is gi
1452True
1453>>> p = weakref.proxy(gi)
1454>>> list(p)
1455['foo!']
1456
1457"""
1458
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001459coroutine_tests = """\
1460Sending a value into a started generator:
1461
1462>>> def f():
1463... print (yield 1)
1464... yield 2
1465>>> g = f()
1466>>> g.next()
14671
1468>>> g.send(42)
146942
14702
1471
1472Sending a value into a new generator produces a TypeError:
1473
1474>>> f().send("foo")
1475Traceback (most recent call last):
1476...
1477TypeError: can't send non-None value to a just-started generator
1478
1479
1480Yield by itself yields None:
1481
1482>>> def f(): yield
1483>>> list(f())
1484[None]
1485
1486
1487
1488An obscene abuse of a yield expression within a generator expression:
1489
1490>>> list((yield 21) for i in range(4))
1491[21, None, 21, None, 21, None, 21, None]
1492
1493And a more sane, but still weird usage:
1494
1495>>> def f(): list(i for i in [(yield 26)])
1496>>> type(f())
1497<type 'generator'>
1498
1499
Neal Norwitz0d62a062006-07-30 06:53:31 +00001500A yield expression with augmented assignment.
1501
1502>>> def coroutine(seq):
1503... count = 0
1504... while count < 200:
1505... count += yield
1506... seq.append(count)
1507>>> seq = []
1508>>> c = coroutine(seq)
1509>>> c.next()
1510>>> print seq
1511[]
1512>>> c.send(10)
1513>>> print seq
1514[10]
1515>>> c.send(10)
1516>>> print seq
1517[10, 20]
1518>>> c.send(10)
1519>>> print seq
1520[10, 20, 30]
1521
1522
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001523Check some syntax errors for yield expressions:
1524
1525>>> f=lambda: (yield 1),(yield 2)
1526Traceback (most recent call last):
1527 ...
Neal Norwitz0d62a062006-07-30 06:53:31 +00001528SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[21]>, line 1)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001529
1530>>> def f(): return lambda x=(yield): 1
1531Traceback (most recent call last):
1532 ...
Neal Norwitz0d62a062006-07-30 06:53:31 +00001533SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[22]>, line 1)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001534
1535>>> def f(): x = yield = y
1536Traceback (most recent call last):
1537 ...
Neal Norwitz0d62a062006-07-30 06:53:31 +00001538SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[23]>, line 1)
1539
1540>>> def f(): (yield bar) = y
1541Traceback (most recent call last):
1542 ...
1543SyntaxError: can't assign to yield expression (<doctest test.test_generators.__test__.coroutine[24]>, line 1)
1544
1545>>> def f(): (yield bar) += y
1546Traceback (most recent call last):
1547 ...
1548SyntaxError: augmented assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[25]>, line 1)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001549
1550
1551Now check some throw() conditions:
1552
1553>>> def f():
1554... while True:
1555... try:
1556... print (yield)
1557... except ValueError,v:
1558... print "caught ValueError (%s)" % (v),
1559>>> import sys
1560>>> g = f()
1561>>> g.next()
1562
1563>>> g.throw(ValueError) # type only
1564caught ValueError ()
1565
1566>>> g.throw(ValueError("xyz")) # value only
1567caught ValueError (xyz)
1568
1569>>> g.throw(ValueError, ValueError(1)) # value+matching type
1570caught ValueError (1)
1571
1572>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1573caught ValueError (1)
1574
Phillip J. Ebybee07122006-03-25 00:05:50 +00001575>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1576caught ValueError (1)
1577
Tim Peterse9fe7e02005-08-07 03:04:58 +00001578>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001579Traceback (most recent call last):
1580 ...
1581TypeError: instance exception may not have a separate value
1582
Tim Peterse9fe7e02005-08-07 03:04:58 +00001583>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001584Traceback (most recent call last):
1585 ...
1586TypeError: throw() third argument must be a traceback object
1587
1588>>> def throw(g,exc):
1589... try:
1590... raise exc
1591... except:
1592... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001593>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001594caught ValueError ()
1595
1596>>> g.send(1)
15971
1598
Tim Peterse9fe7e02005-08-07 03:04:58 +00001599>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001600Traceback (most recent call last):
1601 ...
1602TypeError
1603
1604>>> print g.gi_frame
1605None
1606
1607>>> g.send(2)
1608Traceback (most recent call last):
1609 ...
1610StopIteration
1611
Tim Peterse9fe7e02005-08-07 03:04:58 +00001612>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001613Traceback (most recent call last):
1614 ...
1615ValueError: 6
1616
Tim Peterse9fe7e02005-08-07 03:04:58 +00001617>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001618Traceback (most recent call last):
1619 ...
1620ValueError: 7
1621
Neal Norwitzfcf44352005-11-27 20:37:43 +00001622>>> f().throw("abc") # throw on just-opened generator
1623Traceback (most recent call last):
1624 ...
Phillip J. Ebybee07122006-03-25 00:05:50 +00001625abc
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001626
1627Now let's try closing a generator:
1628
1629>>> def f():
1630... try: yield
1631... except GeneratorExit:
1632... print "exiting"
1633
1634>>> g = f()
1635>>> g.next()
1636>>> g.close()
1637exiting
1638>>> g.close() # should be no-op now
1639
1640>>> f().close() # close on just-opened generator should be fine
1641
Tim Peterse9fe7e02005-08-07 03:04:58 +00001642>>> def f(): yield # an even simpler generator
1643>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001644>>> g = f()
1645>>> g.next()
Tim Peterse9fe7e02005-08-07 03:04:58 +00001646>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001647
1648And finalization:
1649
1650>>> def f():
1651... try: yield
1652... finally:
1653... print "exiting"
1654
1655>>> g = f()
1656>>> g.next()
1657>>> del g
1658exiting
1659
1660
1661Now let's try some ill-behaved generators:
1662
1663>>> def f():
1664... try: yield
1665... except GeneratorExit:
1666... yield "foo!"
1667>>> g = f()
1668>>> g.next()
1669>>> g.close()
1670Traceback (most recent call last):
1671 ...
1672RuntimeError: generator ignored GeneratorExit
1673>>> g.close()
1674
1675
1676Our ill-behaved code should be invoked during GC:
1677
1678>>> import sys, StringIO
1679>>> old, sys.stderr = sys.stderr, StringIO.StringIO()
1680>>> g = f()
1681>>> g.next()
1682>>> del g
1683>>> sys.stderr.getvalue().startswith(
1684... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in "
1685... )
1686True
1687>>> sys.stderr = old
1688
1689
1690And errors thrown during closing should propagate:
1691
1692>>> def f():
1693... try: yield
1694... except GeneratorExit:
1695... raise TypeError("fie!")
1696>>> g = f()
1697>>> g.next()
1698>>> g.close()
1699Traceback (most recent call last):
1700 ...
1701TypeError: fie!
1702
1703
1704Ensure that various yield expression constructs make their
1705enclosing function a generator:
1706
1707>>> def f(): x += yield
1708>>> type(f())
1709<type 'generator'>
1710
1711>>> def f(): x = yield
1712>>> type(f())
1713<type 'generator'>
1714
1715>>> def f(): lambda x=(yield): 1
1716>>> type(f())
1717<type 'generator'>
1718
1719>>> def f(): x=(i for i in (yield) if (yield))
1720>>> type(f())
1721<type 'generator'>
1722
1723>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1724>>> data = [1,2]
1725>>> g = f(data)
1726>>> type(g)
1727<type 'generator'>
1728>>> g.send(None)
1729'a'
1730>>> data
1731[1, 2]
1732>>> g.send(0)
1733'b'
1734>>> data
1735[27, 2]
1736>>> try: g.send(1)
1737... except StopIteration: pass
1738>>> data
1739[27, 27]
1740
1741"""
1742
Thomas Wouters4054b972006-03-28 08:44:55 +00001743refleaks_tests = """
1744Prior to adding cycle-GC support to itertools.tee, this code would leak
1745references. We add it to the standard suite so the routine refleak-tests
1746would trigger if it starts being uncleanable again.
1747
1748>>> import itertools
1749>>> def leak():
1750... class gen:
1751... def __iter__(self):
1752... return self
1753... def next(self):
1754... return self.item
1755... g = gen()
1756... head, tail = itertools.tee(g)
1757... g.item = head
1758... return head
1759>>> it = leak()
1760
1761Make sure to also test the involvement of the tee-internal teedataobject,
1762which stores returned items.
1763
1764>>> item = it.next()
1765
Thomas Wouters60eab2b2006-04-15 22:44:07 +00001766
1767
1768This test leaked at one point due to generator finalization/destruction.
1769It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1770was removed.
1771
1772>>> def leak():
1773... def gen():
1774... while True:
1775... yield g
1776... g = gen()
1777
1778>>> leak()
1779
1780
Thomas Woutersb8f81d42006-04-15 23:27:28 +00001781
1782This test isn't really generator related, but rather exception-in-cleanup
1783related. The coroutine tests (above) just happen to cause an exception in
1784the generator's __del__ (tp_del) method. We can also test for this
1785explicitly, without generators. We do have to redirect stderr to avoid
1786printing warnings and to doublecheck that we actually tested what we wanted
1787to test.
1788
1789>>> import sys, StringIO
1790>>> old = sys.stderr
1791>>> try:
1792... sys.stderr = StringIO.StringIO()
1793... class Leaker:
1794... def __del__(self):
1795... raise RuntimeError
1796...
1797... l = Leaker()
1798... del l
1799... err = sys.stderr.getvalue().strip()
1800... err.startswith(
1801... "Exception exceptions.RuntimeError: RuntimeError() in <"
1802... )
1803... err.endswith("> ignored")
1804... len(err.splitlines())
1805... finally:
1806... sys.stderr = old
1807True
1808True
18091
1810
1811
1812
1813These refleak tests should perhaps be in a testfile of their own,
1814test_generators just happened to be the test that drew these out.
Thomas Wouters4054b972006-03-28 08:44:55 +00001815
1816"""
1817
Tim Petersf6ed0742001-06-27 07:17:57 +00001818__test__ = {"tut": tutorial_tests,
1819 "pep": pep_tests,
1820 "email": email_tests,
1821 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001822 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001823 "conjoin": conjoin_tests,
1824 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001825 "coroutine": coroutine_tests,
Thomas Wouters4054b972006-03-28 08:44:55 +00001826 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001827 }
Tim Peters1def3512001-06-23 20:27:04 +00001828
1829# Magic test name that regrtest.py invokes *after* importing this module.
1830# This worms around a bootstrap problem.
1831# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1832# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001833def test_main(verbose=None):
Barry Warsaw04f357c2002-07-23 19:04:11 +00001834 from test import test_support, test_generators
Tim Peterscca01832004-08-27 15:29:59 +00001835 test_support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001836
1837# This part isn't needed for regrtest, but for running the test directly.
1838if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001839 test_main(1)