blob: 4be1b4c5252d6559a6cabaa1d01036cce3d0e4e0 [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()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000424... self.close = self.generator.close
Tim Peters35302662001-07-02 01:38:33 +0000425...
426... def generate(self):
427... while not self.parent:
428... yield self
429... for x in self.parent.generator:
430... yield x
431...
432... def find(self):
433... return self.generator.next()
434...
435... def union(self, parent):
436... if self.parent:
437... raise ValueError("Sorry, I'm not a root!")
438... self.parent = parent
439...
440... def __str__(self):
441... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000442
443>>> names = "ABCDEFGHIJKLM"
444>>> sets = [disjointSet(name) for name in names]
445>>> roots = sets[:]
446
447>>> import random
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000448>>> gen = random.WichmannHill(42)
Tim Peters35302662001-07-02 01:38:33 +0000449>>> while 1:
450... for s in sets:
451... print "%s->%s" % (s, s.find()),
452... print
453... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000454... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000455... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000456... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000457... s1.union(s2)
458... print "merged", s1, "into", s2
459... else:
460... break
461A->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
462merged D into G
463A->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
464merged C into F
465A->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
466merged L into A
467A->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
468merged H into E
469A->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
470merged B into E
471A->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
472merged J into G
473A->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
474merged E into G
475A->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
476merged M into G
477A->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
478merged I into K
479A->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
480merged K into A
481A->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
482merged F into A
483A->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
484merged A into G
485A->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 +0000486
Tim Peterse9fe7e02005-08-07 03:04:58 +0000487>>> for s in sets: s.close() # break cycles
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000488
Tim Peters6ba5f792001-06-23 20:45:43 +0000489"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000490# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000491
Tim Peters0f9da0a2001-06-23 21:01:47 +0000492# Fun tests (for sufficiently warped notions of "fun").
493
494fun_tests = """
495
496Build up to a recursive Sieve of Eratosthenes generator.
497
498>>> def firstn(g, n):
499... return [g.next() for i in range(n)]
500
501>>> def intsfrom(i):
502... while 1:
503... yield i
504... i += 1
505
506>>> firstn(intsfrom(5), 7)
507[5, 6, 7, 8, 9, 10, 11]
508
509>>> def exclude_multiples(n, ints):
510... for i in ints:
511... if i % n:
512... yield i
513
514>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
515[1, 2, 4, 5, 7, 8]
516
517>>> def sieve(ints):
518... prime = ints.next()
519... yield prime
520... not_divisible_by_prime = exclude_multiples(prime, ints)
521... for p in sieve(not_divisible_by_prime):
522... yield p
523
524>>> primes = sieve(intsfrom(2))
525>>> firstn(primes, 20)
526[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 +0000527
Tim Petersf6ed0742001-06-27 07:17:57 +0000528
Tim Petersb9e9ff12001-06-24 03:44:52 +0000529Another famous problem: generate all integers of the form
530 2**i * 3**j * 5**k
531in increasing order, where i,j,k >= 0. Trickier than it may look at first!
532Try writing it without generators, and correctly, and without generating
5333 internal results for each result output.
534
535>>> def times(n, g):
536... for i in g:
537... yield n * i
538>>> firstn(times(10, intsfrom(1)), 10)
539[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
540
541>>> def merge(g, h):
542... ng = g.next()
543... nh = h.next()
544... while 1:
545... if ng < nh:
546... yield ng
547... ng = g.next()
548... elif ng > nh:
549... yield nh
550... nh = h.next()
551... else:
552... yield ng
553... ng = g.next()
554... nh = h.next()
555
Tim Petersf6ed0742001-06-27 07:17:57 +0000556The following works, but is doing a whale of a lot of redundant work --
557it's not clear how to get the internal uses of m235 to share a single
558generator. Note that me_times2 (etc) each need to see every element in the
559result sequence. So this is an example where lazy lists are more natural
560(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000561
562>>> def m235():
563... yield 1
564... me_times2 = times(2, m235())
565... me_times3 = times(3, m235())
566... me_times5 = times(5, m235())
567... for i in merge(merge(me_times2,
568... me_times3),
569... me_times5):
570... yield i
571
Tim Petersf6ed0742001-06-27 07:17:57 +0000572Don't print "too many" of these -- the implementation above is extremely
573inefficient: each call of m235() leads to 3 recursive calls, and in
574turn each of those 3 more, and so on, and so on, until we've descended
575enough levels to satisfy the print stmts. Very odd: when I printed 5
576lines of results below, this managed to screw up Win98's malloc in "the
577usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
578address space, and it *looked* like a very slow leak.
579
Tim Petersb9e9ff12001-06-24 03:44:52 +0000580>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000581>>> for i in range(3):
Tim Petersb9e9ff12001-06-24 03:44:52 +0000582... print firstn(result, 15)
583[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
584[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
585[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000586
587Heh. Here's one way to get a shared list, complete with an excruciating
588namespace renaming trick. The *pretty* part is that the times() and merge()
589functions can be reused as-is, because they only assume their stream
590arguments are iterable -- a LazyList is the same as a generator to times().
591
592>>> class LazyList:
593... def __init__(self, g):
594... self.sofar = []
595... self.fetch = g.next
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000596... self.close = g.close
Tim Petersee309272001-06-24 05:47:06 +0000597...
598... def __getitem__(self, i):
599... sofar, fetch = self.sofar, self.fetch
600... while i >= len(sofar):
601... sofar.append(fetch())
602... return sofar[i]
603
604>>> def m235():
605... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000606... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000607... me_times2 = times(2, m235)
608... me_times3 = times(3, m235)
609... me_times5 = times(5, m235)
610... for i in merge(merge(me_times2,
611... me_times3),
612... me_times5):
613... yield i
614
Tim Petersf6ed0742001-06-27 07:17:57 +0000615Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000616efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000617
Tim Petersee309272001-06-24 05:47:06 +0000618>>> m235 = LazyList(m235())
619>>> for i in range(5):
620... print [m235[j] for j in range(15*i, 15*(i+1))]
621[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
622[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
623[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
624[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
625[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000626
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000627>>> m235.close()
Tim Petersf6ed0742001-06-27 07:17:57 +0000628
629Ye olde Fibonacci generator, LazyList style.
630
631>>> def fibgen(a, b):
632...
633... def sum(g, h):
634... while 1:
635... yield g.next() + h.next()
636...
637... def tail(g):
638... g.next() # throw first away
639... for x in g:
640... yield x
641...
642... yield a
643... yield b
644... for s in sum(iter(fib),
645... tail(iter(fib))):
646... yield s
647
648>>> fib = LazyList(fibgen(1, 2))
649>>> firstn(iter(fib), 17)
650[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000651>>> fib.close()
Georg Brandl52715f62005-08-24 09:02:29 +0000652
653
654Running after your tail with itertools.tee (new in version 2.4)
655
656The algorithms "m235" (Hamming) and Fibonacci presented above are both
657examples of a whole family of FP (functional programming) algorithms
658where a function produces and returns a list while the production algorithm
659suppose the list as already produced by recursively calling itself.
660For these algorithms to work, they must:
661
662- produce at least a first element without presupposing the existence of
663 the rest of the list
664- produce their elements in a lazy manner
665
666To work efficiently, the beginning of the list must not be recomputed over
667and over again. This is ensured in most FP languages as a built-in feature.
668In python, we have to explicitly maintain a list of already computed results
669and abandon genuine recursivity.
670
671This is what had been attempted above with the LazyList class. One problem
672with that class is that it keeps a list of all of the generated results and
673therefore continually grows. This partially defeats the goal of the generator
674concept, viz. produce the results only as needed instead of producing them
675all and thereby wasting memory.
676
677Thanks to itertools.tee, it is now clear "how to get the internal uses of
678m235 to share a single generator".
679
680>>> from itertools import tee
681>>> def m235():
682... def _m235():
683... yield 1
684... for n in merge(times(2, m2),
685... merge(times(3, m3),
686... times(5, m5))):
687... yield n
688... m2, m3, m5, mRes = tee(_m235(), 4)
689... return mRes
690
691>>> it = m235()
692>>> for i in range(5):
693... print firstn(it, 15)
694[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
695[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
696[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
697[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
698[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
699
700The "tee" function does just what we want. It internally keeps a generated
701result for as long as it has not been "consumed" from all of the duplicated
702iterators, whereupon it is deleted. You can therefore print the hamming
703sequence during hours without increasing memory usage, or very little.
704
705The beauty of it is that recursive running after their tail FP algorithms
706are quite straightforwardly expressed with this Python idiom.
707
708
709Ye olde Fibonacci generator, tee style.
710
711>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +0000712...
Georg Brandl52715f62005-08-24 09:02:29 +0000713... def _isum(g, h):
714... while 1:
715... yield g.next() + h.next()
Tim Peters9e34c042005-08-26 15:20:46 +0000716...
Georg Brandl52715f62005-08-24 09:02:29 +0000717... def _fib():
718... yield 1
719... yield 2
720... fibTail.next() # throw first away
721... for res in _isum(fibHead, fibTail):
722... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000723...
Georg Brandl52715f62005-08-24 09:02:29 +0000724... fibHead, fibTail, fibRes = tee(_fib(), 3)
725... return fibRes
726
727>>> firstn(fib(), 17)
728[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
729
Tim Peters0f9da0a2001-06-23 21:01:47 +0000730"""
731
Tim Petersb6c3cea2001-06-26 03:36:28 +0000732# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
733# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000734
Tim Petersea2e97a2001-06-24 07:10:02 +0000735syntax_tests = """
736
Tim Petersaef8cfa2004-08-27 15:12:49 +0000737>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000738... return 22
739... yield 1
740Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000741 ..
Tim Petersc5684782004-09-13 01:07:12 +0000742SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2)
Tim Petersea2e97a2001-06-24 07:10:02 +0000743
Tim Petersaef8cfa2004-08-27 15:12:49 +0000744>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000745... yield 1
746... return 22
747Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000748 ..
Tim Petersc5684782004-09-13 01:07:12 +0000749SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000750
751"return None" is not the same as "return" in a generator:
752
Tim Petersaef8cfa2004-08-27 15:12:49 +0000753>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000754... yield 1
755... return None
756Traceback (most recent call last):
Tim Peters77dcccc2004-08-27 05:44:51 +0000757 ..
Tim Petersc5684782004-09-13 01:07:12 +0000758SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
Tim Petersea2e97a2001-06-24 07:10:02 +0000759
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000760These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000761
762>>> def f():
763... yield 1
764... return
765
Tim Petersaef8cfa2004-08-27 15:12:49 +0000766>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000767... try:
768... yield 1
769... finally:
770... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000771
Tim Petersaef8cfa2004-08-27 15:12:49 +0000772>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000773... try:
774... try:
Tim Peters3caca232001-12-06 06:23:26 +0000775... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000776... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000777... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000778... except:
779... pass
780... finally:
781... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000782
783>>> def f():
784... try:
785... try:
786... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000787... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000788... except ZeroDivisionError:
789... yield 666
790... except:
791... try:
792... x = 12
793... finally:
794... yield 12
795... except:
796... return
797>>> list(f())
798[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000799
800>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000801... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000802>>> type(f())
803<type 'generator'>
804
Tim Peters08a898f2001-06-28 01:52:22 +0000805
806>>> def f():
807... if 0:
808... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000809>>> type(f())
810<type 'generator'>
811
Tim Peters08a898f2001-06-28 01:52:22 +0000812
813>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000814... if 0:
815... yield 1
816>>> type(f())
817<type 'generator'>
818
819>>> def f():
820... if "":
821... yield None
822>>> type(f())
823<type 'generator'>
824
825>>> def f():
826... return
827... try:
828... if x==4:
829... pass
830... elif 0:
831... try:
Tim Peters3caca232001-12-06 06:23:26 +0000832... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000833... except SyntaxError:
834... pass
835... else:
836... if 0:
837... while 12:
838... x += 1
839... yield 2 # don't blink
840... f(a, b, c, d, e)
841... else:
842... pass
843... except:
844... x = 1
845... return
846>>> type(f())
847<type 'generator'>
848
849>>> def f():
850... if 0:
851... def g():
852... yield 1
853...
854>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000855<type 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000856
857>>> def f():
858... if 0:
859... class C:
860... def __init__(self):
861... yield 1
862... def f(self):
863... yield 2
864>>> type(f())
Guido van Rossum297abad2001-08-16 08:32:39 +0000865<type 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000866
867>>> def f():
868... if 0:
869... return
870... if 0:
871... yield 2
872>>> type(f())
873<type 'generator'>
874
875
Tim Petersaef8cfa2004-08-27 15:12:49 +0000876>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000877... if 0:
878... lambda x: x # shouldn't trigger here
879... return # or here
880... def f(i):
881... return 2*i # or here
882... if 0:
883... return 3 # but *this* sucks (line 8)
884... if 0:
885... yield 2 # because it's a generator
886Traceback (most recent call last):
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000887SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 8)
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000888
889This one caused a crash (see SF bug 567538):
890
891>>> def f():
892... for i in range(3):
893... try:
894... continue
895... finally:
896... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000897...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000898>>> g = f()
899>>> print g.next()
9000
901>>> print g.next()
9021
903>>> print g.next()
9042
905>>> print g.next()
906Traceback (most recent call last):
907StopIteration
Tim Petersea2e97a2001-06-24 07:10:02 +0000908"""
909
Tim Petersbe4f0a72001-06-29 02:41:16 +0000910# conjoin is a simple backtracking generator, named in honor of Icon's
911# "conjunction" control structure. Pass a list of no-argument functions
912# that return iterable objects. Easiest to explain by example: assume the
913# function list [x, y, z] is passed. Then conjoin acts like:
914#
915# def g():
916# values = [None] * 3
917# for values[0] in x():
918# for values[1] in y():
919# for values[2] in z():
920# yield values
921#
922# So some 3-lists of values *may* be generated, each time we successfully
923# get into the innermost loop. If an iterator fails (is exhausted) before
924# then, it "backtracks" to get the next value from the nearest enclosing
925# iterator (the one "to the left"), and starts all over again at the next
926# slot (pumps a fresh iterator). Of course this is most useful when the
927# iterators have side-effects, so that which values *can* be generated at
928# each slot depend on the values iterated at previous slots.
929
930def conjoin(gs):
931
932 values = [None] * len(gs)
933
934 def gen(i, values=values):
935 if i >= len(gs):
936 yield values
937 else:
938 for values[i] in gs[i]():
939 for x in gen(i+1):
940 yield x
941
942 for x in gen(0):
943 yield x
944
Tim Petersc468fd22001-06-30 07:29:44 +0000945# That works fine, but recursing a level and checking i against len(gs) for
946# each item produced is inefficient. By doing manual loop unrolling across
947# generator boundaries, it's possible to eliminate most of that overhead.
948# This isn't worth the bother *in general* for generators, but conjoin() is
949# a core building block for some CPU-intensive generator applications.
950
951def conjoin(gs):
952
953 n = len(gs)
954 values = [None] * n
955
956 # Do one loop nest at time recursively, until the # of loop nests
957 # remaining is divisible by 3.
958
959 def gen(i, values=values):
960 if i >= n:
961 yield values
962
963 elif (n-i) % 3:
964 ip1 = i+1
965 for values[i] in gs[i]():
966 for x in gen(ip1):
967 yield x
968
969 else:
970 for x in _gen3(i):
971 yield x
972
973 # Do three loop nests at a time, recursing only if at least three more
974 # remain. Don't call directly: this is an internal optimization for
975 # gen's use.
976
977 def _gen3(i, values=values):
978 assert i < n and (n-i) % 3 == 0
979 ip1, ip2, ip3 = i+1, i+2, i+3
980 g, g1, g2 = gs[i : ip3]
981
982 if ip3 >= n:
983 # These are the last three, so we can yield values directly.
984 for values[i] in g():
985 for values[ip1] in g1():
986 for values[ip2] in g2():
987 yield values
988
989 else:
990 # At least 6 loop nests remain; peel off 3 and recurse for the
991 # rest.
992 for values[i] in g():
993 for values[ip1] in g1():
994 for values[ip2] in g2():
995 for x in _gen3(ip3):
996 yield x
997
998 for x in gen(0):
999 yield x
1000
unknown31569562001-07-04 22:11:22 +00001001# And one more approach: For backtracking apps like the Knight's Tour
1002# solver below, the number of backtracking levels can be enormous (one
1003# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1004# needs 10,000 levels). In such cases Python is likely to run out of
1005# stack space due to recursion. So here's a recursion-free version of
1006# conjoin too.
1007# NOTE WELL: This allows large problems to be solved with only trivial
1008# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001009# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1010# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001011
1012def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1013 n = len(gs)
1014 values = [None] * n
1015 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001016 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001017 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001018 while 1:
1019 # Descend.
1020 try:
1021 while i < n:
1022 it = iters[i] = gs[i]().next
1023 values[i] = it()
1024 i += 1
1025 except _StopIteration:
1026 pass
unknown31569562001-07-04 22:11:22 +00001027 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001028 assert i == n
1029 yield values
unknown31569562001-07-04 22:11:22 +00001030
Tim Peters9a8c8e22001-07-13 09:12:12 +00001031 # Backtrack until an older iterator can be resumed.
1032 i -= 1
unknown31569562001-07-04 22:11:22 +00001033 while i >= 0:
1034 try:
1035 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001036 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001037 i += 1
1038 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001039 except _StopIteration:
1040 # Continue backtracking.
1041 i -= 1
1042 else:
1043 assert i < 0
1044 break
unknown31569562001-07-04 22:11:22 +00001045
Tim Petersbe4f0a72001-06-29 02:41:16 +00001046# A conjoin-based N-Queens solver.
1047
1048class Queens:
1049 def __init__(self, n):
1050 self.n = n
1051 rangen = range(n)
1052
1053 # Assign a unique int to each column and diagonal.
1054 # columns: n of those, range(n).
1055 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1056 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1057 # based.
1058 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1059 # each, smallest i+j is 0, largest is 2n-2.
1060
1061 # For each square, compute a bit vector of the columns and
1062 # diagonals it covers, and for each row compute a function that
1063 # generates the possiblities for the columns in that row.
1064 self.rowgenerators = []
1065 for i in rangen:
1066 rowuses = [(1L << j) | # column ordinal
1067 (1L << (n + i-j + n-1)) | # NW-SE ordinal
1068 (1L << (n + 2*n-1 + i+j)) # NE-SW ordinal
1069 for j in rangen]
1070
1071 def rowgen(rowuses=rowuses):
1072 for j in rangen:
1073 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001074 if uses & self.used == 0:
1075 self.used |= uses
1076 yield j
1077 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001078
1079 self.rowgenerators.append(rowgen)
1080
1081 # Generate solutions.
1082 def solve(self):
1083 self.used = 0
1084 for row2col in conjoin(self.rowgenerators):
1085 yield row2col
1086
1087 def printsolution(self, row2col):
1088 n = self.n
1089 assert n == len(row2col)
1090 sep = "+" + "-+" * n
1091 print sep
1092 for i in range(n):
1093 squares = [" " for j in range(n)]
1094 squares[row2col[i]] = "Q"
1095 print "|" + "|".join(squares) + "|"
1096 print sep
1097
unknown31569562001-07-04 22:11:22 +00001098# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1099# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1100# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001101# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001102
1103class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001104 def __init__(self, m, n, hard=0):
1105 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001106
Tim Peters9a8c8e22001-07-13 09:12:12 +00001107 # solve() will set up succs[i] to be a list of square #i's
1108 # successors.
1109 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001110
Tim Peters9a8c8e22001-07-13 09:12:12 +00001111 # Remove i0 from each of its successor's successor lists, i.e.
1112 # successors can't go back to i0 again. Return 0 if we can
1113 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001114
Tim Peters9a8c8e22001-07-13 09:12:12 +00001115 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001116 # If we remove all exits from a free square, we're dead:
1117 # even if we move to it next, we can't leave it again.
1118 # If we create a square with one exit, we must visit it next;
1119 # else somebody else will have to visit it, and since there's
1120 # only one adjacent, there won't be a way to leave it again.
1121 # Finelly, if we create more than one free square with a
1122 # single exit, we can only move to one of them next, leaving
1123 # the other one a dead end.
1124 ne0 = ne1 = 0
1125 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001126 s = succs[i]
1127 s.remove(i0)
1128 e = len(s)
1129 if e == 0:
1130 ne0 += 1
1131 elif e == 1:
1132 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001133 return ne0 == 0 and ne1 < 2
1134
Tim Peters9a8c8e22001-07-13 09:12:12 +00001135 # Put i0 back in each of its successor's successor lists.
1136
1137 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001138 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001139 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001140
1141 # Generate the first move.
1142 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001143 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001144 return
1145
unknown31569562001-07-04 22:11:22 +00001146 # Since we're looking for a cycle, it doesn't matter where we
1147 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001148 corner = self.coords2index(0, 0)
1149 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001150 self.lastij = corner
1151 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001152 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001153
1154 # Generate the second moves.
1155 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001156 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001157 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001158 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001159 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001160 assert len(succs[corner]) == 2
1161 assert self.coords2index(1, 2) in succs[corner]
1162 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001163 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001164 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001165 # to (0, 0). Save its index in self.final so that moves before
1166 # the last know it must be kept free.
1167 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001168 this = self.coords2index(i, j)
1169 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001170 self.final = final
unknown31569562001-07-04 22:11:22 +00001171
Tim Peters9a8c8e22001-07-13 09:12:12 +00001172 remove_from_successors(this)
1173 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001174 self.lastij = this
1175 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001176 succs[final].remove(corner)
1177 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001178
Tim Peters9a8c8e22001-07-13 09:12:12 +00001179 # Generate moves 3 thru m*n-1.
1180 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001181 # If some successor has only one exit, must take it.
1182 # Else favor successors with fewer exits.
1183 candidates = []
1184 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001185 e = len(succs[i])
1186 assert e > 0, "else remove_from_successors() pruning flawed"
1187 if e == 1:
1188 candidates = [(e, i)]
1189 break
1190 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001191 else:
1192 candidates.sort()
1193
1194 for e, i in candidates:
1195 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001196 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001197 self.lastij = i
1198 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001199 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001200
Tim Peters9a8c8e22001-07-13 09:12:12 +00001201 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001202 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001203 # Since the # of backtracking levels is m*n, a poor move early on
1204 # can take eons to undo. Smallest square board for which this
1205 # matters a lot is 52x52.
1206 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001207 # If some successor has only one exit, must take it.
1208 # Else favor successors with fewer exits.
1209 # Break ties via max distance from board centerpoint (favor
1210 # corners and edges whenever possible).
1211 candidates = []
1212 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001213 e = len(succs[i])
1214 assert e > 0, "else remove_from_successors() pruning flawed"
1215 if e == 1:
1216 candidates = [(e, 0, i)]
1217 break
1218 i1, j1 = self.index2coords(i)
1219 d = (i1 - vmid)**2 + (j1 - hmid)**2
1220 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001221 else:
1222 candidates.sort()
1223
1224 for e, d, i in candidates:
1225 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001226 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001227 self.lastij = i
1228 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001229 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001230
1231 # Generate the last move.
1232 def last():
1233 assert self.final in succs[self.lastij]
1234 yield self.final
1235
Tim Peters9a8c8e22001-07-13 09:12:12 +00001236 if m*n < 4:
1237 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001238 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001239 self.squaregenerators = [first, second] + \
1240 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001241 [last]
1242
Tim Peters9a8c8e22001-07-13 09:12:12 +00001243 def coords2index(self, i, j):
1244 assert 0 <= i < self.m
1245 assert 0 <= j < self.n
1246 return i * self.n + j
1247
1248 def index2coords(self, index):
1249 assert 0 <= index < self.m * self.n
1250 return divmod(index, self.n)
1251
1252 def _init_board(self):
1253 succs = self.succs
1254 del succs[:]
1255 m, n = self.m, self.n
1256 c2i = self.coords2index
1257
1258 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1259 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1260 rangen = range(n)
1261 for i in range(m):
1262 for j in rangen:
1263 s = [c2i(i+io, j+jo) for io, jo in offsets
1264 if 0 <= i+io < m and
1265 0 <= j+jo < n]
1266 succs.append(s)
1267
unknown31569562001-07-04 22:11:22 +00001268 # Generate solutions.
1269 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001270 self._init_board()
1271 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001272 yield x
1273
1274 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001275 m, n = self.m, self.n
1276 assert len(x) == m*n
1277 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001278 format = "%" + str(w) + "d"
1279
Tim Peters9a8c8e22001-07-13 09:12:12 +00001280 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001281 k = 1
1282 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001283 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001284 squares[i1][j1] = format % k
1285 k += 1
1286
1287 sep = "+" + ("-" * w + "+") * n
1288 print sep
Tim Peters9a8c8e22001-07-13 09:12:12 +00001289 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001290 row = squares[i]
1291 print "|" + "|".join(row) + "|"
1292 print sep
1293
Tim Petersbe4f0a72001-06-29 02:41:16 +00001294conjoin_tests = """
1295
1296Generate the 3-bit binary numbers in order. This illustrates dumbest-
1297possible use of conjoin, just to generate the full cross-product.
1298
unknown31569562001-07-04 22:11:22 +00001299>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001300... print c
1301[0, 0, 0]
1302[0, 0, 1]
1303[0, 1, 0]
1304[0, 1, 1]
1305[1, 0, 0]
1306[1, 0, 1]
1307[1, 1, 0]
1308[1, 1, 1]
1309
Tim Petersc468fd22001-06-30 07:29:44 +00001310For efficiency in typical backtracking apps, conjoin() yields the same list
1311object each time. So if you want to save away a full account of its
1312generated sequence, you need to copy its results.
1313
1314>>> def gencopy(iterator):
1315... for x in iterator:
1316... yield x[:]
1317
1318>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001319... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Tim Petersc468fd22001-06-30 07:29:44 +00001320... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n
Guido van Rossum77f6a652002-04-03 22:41:51 +000013210 1 True True
13221 2 True True
13232 4 True True
13243 8 True True
13254 16 True True
13265 32 True True
13276 64 True True
13287 128 True True
13298 256 True True
13309 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001331
Tim Petersbe4f0a72001-06-29 02:41:16 +00001332And run an 8-queens solver.
1333
1334>>> q = Queens(8)
1335>>> LIMIT = 2
1336>>> count = 0
1337>>> for row2col in q.solve():
1338... count += 1
1339... if count <= LIMIT:
1340... print "Solution", count
1341... q.printsolution(row2col)
1342Solution 1
1343+-+-+-+-+-+-+-+-+
1344|Q| | | | | | | |
1345+-+-+-+-+-+-+-+-+
1346| | | | |Q| | | |
1347+-+-+-+-+-+-+-+-+
1348| | | | | | | |Q|
1349+-+-+-+-+-+-+-+-+
1350| | | | | |Q| | |
1351+-+-+-+-+-+-+-+-+
1352| | |Q| | | | | |
1353+-+-+-+-+-+-+-+-+
1354| | | | | | |Q| |
1355+-+-+-+-+-+-+-+-+
1356| |Q| | | | | | |
1357+-+-+-+-+-+-+-+-+
1358| | | |Q| | | | |
1359+-+-+-+-+-+-+-+-+
1360Solution 2
1361+-+-+-+-+-+-+-+-+
1362|Q| | | | | | | |
1363+-+-+-+-+-+-+-+-+
1364| | | | | |Q| | |
1365+-+-+-+-+-+-+-+-+
1366| | | | | | | |Q|
1367+-+-+-+-+-+-+-+-+
1368| | |Q| | | | | |
1369+-+-+-+-+-+-+-+-+
1370| | | | | | |Q| |
1371+-+-+-+-+-+-+-+-+
1372| | | |Q| | | | |
1373+-+-+-+-+-+-+-+-+
1374| |Q| | | | | | |
1375+-+-+-+-+-+-+-+-+
1376| | | | |Q| | | |
1377+-+-+-+-+-+-+-+-+
1378
1379>>> print count, "solutions in all."
138092 solutions in all.
unknown31569562001-07-04 22:11:22 +00001381
1382And run a Knight's Tour on a 10x10 board. Note that there are about
138320,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1384
Tim Peters9a8c8e22001-07-13 09:12:12 +00001385>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001386>>> LIMIT = 2
1387>>> count = 0
1388>>> for x in k.solve():
1389... count += 1
1390... if count <= LIMIT:
1391... print "Solution", count
1392... k.printsolution(x)
1393... else:
1394... break
1395Solution 1
1396+---+---+---+---+---+---+---+---+---+---+
1397| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1398+---+---+---+---+---+---+---+---+---+---+
1399| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1400+---+---+---+---+---+---+---+---+---+---+
1401| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1402+---+---+---+---+---+---+---+---+---+---+
1403| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1404+---+---+---+---+---+---+---+---+---+---+
1405| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1406+---+---+---+---+---+---+---+---+---+---+
1407| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1408+---+---+---+---+---+---+---+---+---+---+
1409| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1410+---+---+---+---+---+---+---+---+---+---+
1411| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1412+---+---+---+---+---+---+---+---+---+---+
1413| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1414+---+---+---+---+---+---+---+---+---+---+
1415| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1416+---+---+---+---+---+---+---+---+---+---+
1417Solution 2
1418+---+---+---+---+---+---+---+---+---+---+
1419| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1420+---+---+---+---+---+---+---+---+---+---+
1421| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1422+---+---+---+---+---+---+---+---+---+---+
1423| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1424+---+---+---+---+---+---+---+---+---+---+
1425| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1426+---+---+---+---+---+---+---+---+---+---+
1427| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1428+---+---+---+---+---+---+---+---+---+---+
1429| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1430+---+---+---+---+---+---+---+---+---+---+
1431| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1432+---+---+---+---+---+---+---+---+---+---+
1433| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1434+---+---+---+---+---+---+---+---+---+---+
1435| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1436+---+---+---+---+---+---+---+---+---+---+
1437| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1438+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001439"""
1440
Fred Drake56d12662002-08-09 18:37:10 +00001441weakref_tests = """\
1442Generators are weakly referencable:
1443
1444>>> import weakref
1445>>> def gen():
1446... yield 'foo!'
1447...
1448>>> wr = weakref.ref(gen)
1449>>> wr() is gen
1450True
1451>>> p = weakref.proxy(gen)
1452
1453Generator-iterators are weakly referencable as well:
1454
1455>>> gi = gen()
1456>>> wr = weakref.ref(gi)
1457>>> wr() is gi
1458True
1459>>> p = weakref.proxy(gi)
1460>>> list(p)
1461['foo!']
1462
1463"""
1464
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001465coroutine_tests = """\
1466Sending a value into a started generator:
1467
1468>>> def f():
1469... print (yield 1)
1470... yield 2
1471>>> g = f()
1472>>> g.next()
14731
1474>>> g.send(42)
147542
14762
1477
1478Sending a value into a new generator produces a TypeError:
1479
1480>>> f().send("foo")
1481Traceback (most recent call last):
1482...
1483TypeError: can't send non-None value to a just-started generator
1484
1485
1486Yield by itself yields None:
1487
1488>>> def f(): yield
1489>>> list(f())
1490[None]
1491
1492
1493
1494An obscene abuse of a yield expression within a generator expression:
1495
1496>>> list((yield 21) for i in range(4))
1497[21, None, 21, None, 21, None, 21, None]
1498
1499And a more sane, but still weird usage:
1500
1501>>> def f(): list(i for i in [(yield 26)])
1502>>> type(f())
1503<type 'generator'>
1504
1505
1506Check some syntax errors for yield expressions:
1507
1508>>> f=lambda: (yield 1),(yield 2)
1509Traceback (most recent call last):
1510 ...
1511SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[10]>, line 1)
1512
1513>>> def f(): return lambda x=(yield): 1
1514Traceback (most recent call last):
1515 ...
1516SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[11]>, line 1)
1517
1518>>> def f(): x = yield = y
1519Traceback (most recent call last):
1520 ...
1521SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[12]>, line 1)
1522
1523
1524Now check some throw() conditions:
1525
1526>>> def f():
1527... while True:
1528... try:
1529... print (yield)
1530... except ValueError,v:
1531... print "caught ValueError (%s)" % (v),
1532>>> import sys
1533>>> g = f()
1534>>> g.next()
1535
1536>>> g.throw(ValueError) # type only
1537caught ValueError ()
1538
1539>>> g.throw(ValueError("xyz")) # value only
1540caught ValueError (xyz)
1541
1542>>> g.throw(ValueError, ValueError(1)) # value+matching type
1543caught ValueError (1)
1544
1545>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1546caught ValueError (1)
1547
Tim Peterse9fe7e02005-08-07 03:04:58 +00001548>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001549Traceback (most recent call last):
1550 ...
1551TypeError: instance exception may not have a separate value
1552
Tim Peterse9fe7e02005-08-07 03:04:58 +00001553>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001554Traceback (most recent call last):
1555 ...
1556TypeError: throw() third argument must be a traceback object
1557
1558>>> def throw(g,exc):
1559... try:
1560... raise exc
1561... except:
1562... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001563>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001564caught ValueError ()
1565
1566>>> g.send(1)
15671
1568
Tim Peterse9fe7e02005-08-07 03:04:58 +00001569>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001570Traceback (most recent call last):
1571 ...
1572TypeError
1573
1574>>> print g.gi_frame
1575None
1576
1577>>> g.send(2)
1578Traceback (most recent call last):
1579 ...
1580StopIteration
1581
Tim Peterse9fe7e02005-08-07 03:04:58 +00001582>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001583Traceback (most recent call last):
1584 ...
1585ValueError: 6
1586
Tim Peterse9fe7e02005-08-07 03:04:58 +00001587>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001588Traceback (most recent call last):
1589 ...
1590ValueError: 7
1591
Neal Norwitzfcf44352005-11-27 20:37:43 +00001592>>> f().throw("abc") # throw on just-opened generator
1593Traceback (most recent call last):
1594 ...
1595TypeError: exceptions must be classes, or instances, not str
1596
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001597
1598Now let's try closing a generator:
1599
1600>>> def f():
1601... try: yield
1602... except GeneratorExit:
1603... print "exiting"
1604
1605>>> g = f()
1606>>> g.next()
1607>>> g.close()
1608exiting
1609>>> g.close() # should be no-op now
1610
1611>>> f().close() # close on just-opened generator should be fine
1612
Tim Peterse9fe7e02005-08-07 03:04:58 +00001613>>> def f(): yield # an even simpler generator
1614>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001615>>> g = f()
1616>>> g.next()
Tim Peterse9fe7e02005-08-07 03:04:58 +00001617>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001618
1619And finalization:
1620
1621>>> def f():
1622... try: yield
1623... finally:
1624... print "exiting"
1625
1626>>> g = f()
1627>>> g.next()
1628>>> del g
1629exiting
1630
1631
1632Now let's try some ill-behaved generators:
1633
1634>>> def f():
1635... try: yield
1636... except GeneratorExit:
1637... yield "foo!"
1638>>> g = f()
1639>>> g.next()
1640>>> g.close()
1641Traceback (most recent call last):
1642 ...
1643RuntimeError: generator ignored GeneratorExit
1644>>> g.close()
1645
1646
1647Our ill-behaved code should be invoked during GC:
1648
1649>>> import sys, StringIO
1650>>> old, sys.stderr = sys.stderr, StringIO.StringIO()
1651>>> g = f()
1652>>> g.next()
1653>>> del g
1654>>> sys.stderr.getvalue().startswith(
1655... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in "
1656... )
1657True
1658>>> sys.stderr = old
1659
1660
1661And errors thrown during closing should propagate:
1662
1663>>> def f():
1664... try: yield
1665... except GeneratorExit:
1666... raise TypeError("fie!")
1667>>> g = f()
1668>>> g.next()
1669>>> g.close()
1670Traceback (most recent call last):
1671 ...
1672TypeError: fie!
1673
1674
1675Ensure that various yield expression constructs make their
1676enclosing function a generator:
1677
1678>>> def f(): x += yield
1679>>> type(f())
1680<type 'generator'>
1681
1682>>> def f(): x = yield
1683>>> type(f())
1684<type 'generator'>
1685
1686>>> def f(): lambda x=(yield): 1
1687>>> type(f())
1688<type 'generator'>
1689
1690>>> def f(): x=(i for i in (yield) if (yield))
1691>>> type(f())
1692<type 'generator'>
1693
1694>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1695>>> data = [1,2]
1696>>> g = f(data)
1697>>> type(g)
1698<type 'generator'>
1699>>> g.send(None)
1700'a'
1701>>> data
1702[1, 2]
1703>>> g.send(0)
1704'b'
1705>>> data
1706[27, 2]
1707>>> try: g.send(1)
1708... except StopIteration: pass
1709>>> data
1710[27, 27]
1711
1712"""
1713
Tim Petersf6ed0742001-06-27 07:17:57 +00001714__test__ = {"tut": tutorial_tests,
1715 "pep": pep_tests,
1716 "email": email_tests,
1717 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001718 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001719 "conjoin": conjoin_tests,
1720 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001721 "coroutine": coroutine_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001722 }
Tim Peters1def3512001-06-23 20:27:04 +00001723
1724# Magic test name that regrtest.py invokes *after* importing this module.
1725# This worms around a bootstrap problem.
1726# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1727# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001728def test_main(verbose=None):
Barry Warsaw04f357c2002-07-23 19:04:11 +00001729 from test import test_support, test_generators
Tim Peterscca01832004-08-27 15:29:59 +00001730 test_support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001731
1732# This part isn't needed for regrtest, but for running the test directly.
1733if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001734 test_main(1)