blob: 992126ff05d893ce95900a0ff01d49046951bb39 [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():
Guido van Rossum7131f842007-02-09 20:13:25 +00009 ... print(i)
Tim Petersb9e9ff12001-06-24 03:44:52 +000010 1
11 2
Tim Peters1def3512001-06-23 20:27:04 +000012 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +000013 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000014 1
Georg Brandla18af4e2007-04-21 15:47:16 +000015 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000016 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
Georg Brandla18af4e2007-04-21 15:47:16 +000020 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000021 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()
Georg Brandla18af4e2007-04-21 15:47:16 +000034 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000035 1
Georg Brandla18af4e2007-04-21 15:47:16 +000036 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000037 Traceback (most recent call last):
38 File "<stdin>", line 1, in ?
39 File "<stdin>", line 3, in f
40 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +000041 >>> next(g) # once stopped, can't be resumed
Tim Peters1def3512001-06-23 20:27:04 +000042 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()
Georg Brandla18af4e2007-04-21 15:47:16 +000054 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000055 1
Georg Brandla18af4e2007-04-21 15:47:16 +000056 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000057 Traceback (most recent call last):
58 File "<stdin>", line 1, in ?
59 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +000060 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000061 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
Guido van Rossum7131f842007-02-09 20:13:25 +000081 >>> print(list(g2()))
Tim Peters1def3512001-06-23 20:27:04 +000082 [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)
Georg Brandla18af4e2007-04-21 15:47:16 +0000108 ... print("creator", next(r))
Tim Peters1def3512001-06-23 20:27:04 +0000109 ... return r
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000110 ...
Tim Peters1def3512001-06-23 20:27:04 +0000111 >>> def caller():
112 ... r = creator()
113 ... for i in r:
Guido van Rossum7131f842007-02-09 20:13:25 +0000114 ... print("caller", i)
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000115 ...
Tim Peters1def3512001-06-23 20:27:04 +0000116 >>> 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():
Georg Brandla18af4e2007-04-21 15:47:16 +0000144 ... i = next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000145 ... yield i
146 >>> me = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000147 >>> next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000148 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
Guido van Rossum7131f842007-02-09 20:13:25 +0000164 >>> print(list(f1()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000165 []
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
Guido van Rossum7131f842007-02-09 20:13:25 +0000174 >>> print(list(f2()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000175 [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()
Georg Brandla18af4e2007-04-21 15:47:16 +0000188 >>> next(k)
Tim Peters6ba5f792001-06-23 20:45:43 +0000189 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
Georg Brandla18af4e2007-04-21 15:47:16 +0000194 >>> next(k) # and the generator cannot be resumed
Tim Peters6ba5f792001-06-23 20:45:43 +0000195 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
Guido van Rossum7131f842007-02-09 20:13:25 +0000224 >>> print(list(f()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000225 [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:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000273 ... print(' '+x, end='')
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
Tim Peters6ba5f792001-06-23 20:45:43 +0000275
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:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000294 ... print(' '+x, end='')
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
Tim Peters6ba5f792001-06-23 20:45:43 +0000296
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
Guido van Rossum805365e2007-05-07 22:24:25 +0000346>>> seq = list(range(1, 5))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000347>>> for k in range(len(seq) + 2):
Guido van Rossum7131f842007-02-09 20:13:25 +0000348... print("%d-combs of %s:" % (k, seq))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000349... for c in gcomb(seq, k):
Guido van Rossum7131f842007-02-09 20:13:25 +0000350... print(" ", c)
Tim Petersb2bc6a92001-06-24 10:14:27 +00003510-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)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000380<class 'function'>
Tim Peters3e7b1a02001-06-25 19:46:25 +0000381>>> i = g()
382>>> type(i)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000383<class 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000384>>> [s for s in dir(i) if not s.startswith('_')]
Christian Heimesaf98da12008-01-27 15:18:18 +0000385['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw']
Georg Brandla18af4e2007-04-21 15:47:16 +0000386>>> print(i.__next__.__doc__)
387x.__next__() <==> next(x)
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)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000399<class 'frame'>
Tim Peterse77f2e22001-06-26 22:24:51 +0000400>>> i.gi_running = 42
401Traceback (most recent call last):
402 ...
Collin Winter42dae6a2007-03-28 21:44:53 +0000403AttributeError: 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
Georg Brandla18af4e2007-04-21 15:47:16 +0000409>>> next(me)
Tim Peterse77f2e22001-06-26 22:24:51 +00004101
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):
Georg Brandla18af4e2007-04-21 15:47:16 +0000432... return next(self.generator)
Tim Peters35302662001-07-02 01:38:33 +0000433...
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 Hettinger28de64f2008-01-13 23:40:30 +0000447>>> gen = random.Random(42)
Tim Peters35302662001-07-02 01:38:33 +0000448>>> while 1:
449... for s in sets:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000450... print(" %s->%s" % (s, s.find()), end='')
Guido van Rossum7131f842007-02-09 20:13:25 +0000451... print()
Tim Peters35302662001-07-02 01:38:33 +0000452... 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)
Guido van Rossum7131f842007-02-09 20:13:25 +0000457... print("merged", s1, "into", s2)
Tim Peters35302662001-07-02 01:38:33 +0000458... else:
459... break
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000460 A->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
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000461merged I into A
462 A->A B->B C->C D->D E->E F->F G->G H->H I->A J->J K->K L->L M->M
463merged D into C
464 A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->K L->L M->M
465merged K into H
466 A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->H L->L M->M
Tim Peters35302662001-07-02 01:38:33 +0000467merged L into A
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000468 A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->H L->A M->M
469merged E into A
470 A->A B->B C->C D->C E->A F->F G->G H->H I->A J->J K->H L->A M->M
471merged B into G
472 A->A B->G C->C D->C E->A F->F G->G H->H I->A J->J K->H L->A M->M
473merged A into F
474 A->F B->G C->C D->C E->F F->F G->G H->H I->F J->J K->H L->F M->M
475merged H into G
476 A->F B->G C->C D->C E->F F->F G->G H->G I->F J->J K->G L->F M->M
477merged F into J
478 A->J B->G C->C D->C E->J F->J G->G H->G I->J J->J K->G L->J M->M
479merged M into C
480 A->J B->G C->C D->C E->J F->J G->G H->G I->J J->J K->G L->J M->C
Tim Peters35302662001-07-02 01:38:33 +0000481merged J into G
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000482 A->G B->G C->C D->C E->G F->G G->G H->G I->G J->G K->G L->G M->C
483merged C into G
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000484 A->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):
Georg Brandla18af4e2007-04-21 15:47:16 +0000496... return [next(g) for i in range(n)]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000497
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):
Georg Brandla18af4e2007-04-21 15:47:16 +0000515... prime = next(ints)
Tim Peters0f9da0a2001-06-23 21:01:47 +0000516... 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):
Georg Brandla18af4e2007-04-21 15:47:16 +0000539... ng = next(g)
540... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000541... while 1:
542... if ng < nh:
543... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000544... ng = next(g)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000545... elif ng > nh:
546... yield nh
Georg Brandla18af4e2007-04-21 15:47:16 +0000547... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000548... else:
549... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000550... ng = next(g)
551... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000552
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):
Guido van Rossum7131f842007-02-09 20:13:25 +0000579... print(firstn(result, 15))
Tim Petersb9e9ff12001-06-24 03:44:52 +0000580[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 = []
Georg Brandla18af4e2007-04-21 15:47:16 +0000592... self.fetch = g.__next__
Tim Petersee309272001-06-24 05:47:06 +0000593...
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):
Guido van Rossum7131f842007-02-09 20:13:25 +0000616... print([m235[j] for j in range(15*i, 15*(i+1))])
Tim Petersee309272001-06-24 05:47:06 +0000617[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:
Georg Brandla18af4e2007-04-21 15:47:16 +0000629... yield next(g) + next(h)
Tim Petersf6ed0742001-06-27 07:17:57 +0000630...
631... def tail(g):
Georg Brandla18af4e2007-04-21 15:47:16 +0000632... next(g) # throw first away
Tim Petersf6ed0742001-06-27 07:17:57 +0000633... 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
671m235 to share a single generator".
672
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 Wouters49fd7fa2006-04-21 10:40:58 +0000681... m1 = _m235()
682... m2, m3, m5, mRes = tee(m1, 4)
Georg Brandl52715f62005-08-24 09:02:29 +0000683... return mRes
684
685>>> it = m235()
686>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000687... print(firstn(it, 15))
Georg Brandl52715f62005-08-24 09:02:29 +0000688[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
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000699The beauty of it is that recursive running-after-their-tail FP algorithms
Georg Brandl52715f62005-08-24 09:02:29 +0000700are quite straightforwardly expressed with this Python idiom.
701
Georg Brandl52715f62005-08-24 09:02:29 +0000702Ye 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:
Georg Brandla18af4e2007-04-21 15:47:16 +0000708... yield next(g) + next(h)
Tim Peters9e34c042005-08-26 15:20:46 +0000709...
Georg Brandl52715f62005-08-24 09:02:29 +0000710... def _fib():
711... yield 1
712... yield 2
Georg Brandla18af4e2007-04-21 15:47:16 +0000713... next(fibTail) # throw first away
Georg Brandl52715f62005-08-24 09:02:29 +0000714... for res in _isum(fibHead, fibTail):
715... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000716...
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000717... realfib = _fib()
718... fibHead, fibTail, fibRes = tee(realfib, 3)
Georg Brandl52715f62005-08-24 09:02:29 +0000719... return fibRes
720
721>>> firstn(fib(), 17)
722[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 ..
Guido van Rossum33d26892007-08-05 15:29:28 +0000736SyntaxError: 'return' with argument inside generator
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 ..
Guido van Rossum33d26892007-08-05 15:29:28 +0000743SyntaxError: 'return' with argument inside generator
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 ..
Guido van Rossum33d26892007-08-05 15:29:28 +0000752SyntaxError: 'return' with argument inside generator
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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000797<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000798
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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000804<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000805
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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000811<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000812
813>>> def f():
814... if "":
815... yield None
816>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000817<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000818
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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000841<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000842
843>>> def f():
844... if 0:
845... def g():
846... yield 1
847...
848>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000849<class '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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000859<class '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())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000867<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +0000868
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:
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000879... yield 2 # because it's a generator (line 10)
Tim Peters08a898f2001-06-28 01:52:22 +0000880Traceback (most recent call last):
Guido van Rossum33d26892007-08-05 15:29:28 +0000881SyntaxError: 'return' with argument inside generator
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()
Georg Brandla18af4e2007-04-21 15:47:16 +0000893>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008940
Georg Brandla18af4e2007-04-21 15:47:16 +0000895>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008961
Georg Brandla18af4e2007-04-21 15:47:16 +0000897>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008982
Georg Brandla18af4e2007-04-21 15:47:16 +0000899>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000900Traceback (most recent call last):
901StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +0000902
903
904Test the gi_code attribute
905
906>>> def f():
907... yield 5
908...
909>>> g = f()
910>>> g.gi_code is f.__code__
911True
912>>> next(g)
9135
914>>> next(g)
915Traceback (most recent call last):
916StopIteration
917>>> g.gi_code is f.__code__
918True
919
Tim Petersea2e97a2001-06-24 07:10:02 +0000920"""
921
Tim Petersbe4f0a72001-06-29 02:41:16 +0000922# conjoin is a simple backtracking generator, named in honor of Icon's
923# "conjunction" control structure. Pass a list of no-argument functions
924# that return iterable objects. Easiest to explain by example: assume the
925# function list [x, y, z] is passed. Then conjoin acts like:
926#
927# def g():
928# values = [None] * 3
929# for values[0] in x():
930# for values[1] in y():
931# for values[2] in z():
932# yield values
933#
934# So some 3-lists of values *may* be generated, each time we successfully
935# get into the innermost loop. If an iterator fails (is exhausted) before
936# then, it "backtracks" to get the next value from the nearest enclosing
937# iterator (the one "to the left"), and starts all over again at the next
938# slot (pumps a fresh iterator). Of course this is most useful when the
939# iterators have side-effects, so that which values *can* be generated at
940# each slot depend on the values iterated at previous slots.
941
942def conjoin(gs):
943
944 values = [None] * len(gs)
945
946 def gen(i, values=values):
947 if i >= len(gs):
948 yield values
949 else:
950 for values[i] in gs[i]():
951 for x in gen(i+1):
952 yield x
953
954 for x in gen(0):
955 yield x
956
Tim Petersc468fd22001-06-30 07:29:44 +0000957# That works fine, but recursing a level and checking i against len(gs) for
958# each item produced is inefficient. By doing manual loop unrolling across
959# generator boundaries, it's possible to eliminate most of that overhead.
960# This isn't worth the bother *in general* for generators, but conjoin() is
961# a core building block for some CPU-intensive generator applications.
962
963def conjoin(gs):
964
965 n = len(gs)
966 values = [None] * n
967
968 # Do one loop nest at time recursively, until the # of loop nests
969 # remaining is divisible by 3.
970
971 def gen(i, values=values):
972 if i >= n:
973 yield values
974
975 elif (n-i) % 3:
976 ip1 = i+1
977 for values[i] in gs[i]():
978 for x in gen(ip1):
979 yield x
980
981 else:
982 for x in _gen3(i):
983 yield x
984
985 # Do three loop nests at a time, recursing only if at least three more
986 # remain. Don't call directly: this is an internal optimization for
987 # gen's use.
988
989 def _gen3(i, values=values):
990 assert i < n and (n-i) % 3 == 0
991 ip1, ip2, ip3 = i+1, i+2, i+3
992 g, g1, g2 = gs[i : ip3]
993
994 if ip3 >= n:
995 # These are the last three, so we can yield values directly.
996 for values[i] in g():
997 for values[ip1] in g1():
998 for values[ip2] in g2():
999 yield values
1000
1001 else:
1002 # At least 6 loop nests remain; peel off 3 and recurse for the
1003 # rest.
1004 for values[i] in g():
1005 for values[ip1] in g1():
1006 for values[ip2] in g2():
1007 for x in _gen3(ip3):
1008 yield x
1009
1010 for x in gen(0):
1011 yield x
1012
unknown31569562001-07-04 22:11:22 +00001013# And one more approach: For backtracking apps like the Knight's Tour
1014# solver below, the number of backtracking levels can be enormous (one
1015# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1016# needs 10,000 levels). In such cases Python is likely to run out of
1017# stack space due to recursion. So here's a recursion-free version of
1018# conjoin too.
1019# NOTE WELL: This allows large problems to be solved with only trivial
1020# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001021# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1022# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001023
1024def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1025 n = len(gs)
1026 values = [None] * n
1027 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001028 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001029 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001030 while 1:
1031 # Descend.
1032 try:
1033 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001034 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001035 values[i] = it()
1036 i += 1
1037 except _StopIteration:
1038 pass
unknown31569562001-07-04 22:11:22 +00001039 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001040 assert i == n
1041 yield values
unknown31569562001-07-04 22:11:22 +00001042
Tim Peters9a8c8e22001-07-13 09:12:12 +00001043 # Backtrack until an older iterator can be resumed.
1044 i -= 1
unknown31569562001-07-04 22:11:22 +00001045 while i >= 0:
1046 try:
1047 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001048 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001049 i += 1
1050 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001051 except _StopIteration:
1052 # Continue backtracking.
1053 i -= 1
1054 else:
1055 assert i < 0
1056 break
unknown31569562001-07-04 22:11:22 +00001057
Tim Petersbe4f0a72001-06-29 02:41:16 +00001058# A conjoin-based N-Queens solver.
1059
1060class Queens:
1061 def __init__(self, n):
1062 self.n = n
1063 rangen = range(n)
1064
1065 # Assign a unique int to each column and diagonal.
1066 # columns: n of those, range(n).
1067 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1068 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1069 # based.
1070 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1071 # each, smallest i+j is 0, largest is 2n-2.
1072
1073 # For each square, compute a bit vector of the columns and
1074 # diagonals it covers, and for each row compute a function that
1075 # generates the possiblities for the columns in that row.
1076 self.rowgenerators = []
1077 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001078 rowuses = [(1 << j) | # column ordinal
1079 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1080 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001081 for j in rangen]
1082
1083 def rowgen(rowuses=rowuses):
1084 for j in rangen:
1085 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001086 if uses & self.used == 0:
1087 self.used |= uses
1088 yield j
1089 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001090
1091 self.rowgenerators.append(rowgen)
1092
1093 # Generate solutions.
1094 def solve(self):
1095 self.used = 0
1096 for row2col in conjoin(self.rowgenerators):
1097 yield row2col
1098
1099 def printsolution(self, row2col):
1100 n = self.n
1101 assert n == len(row2col)
1102 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001103 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001104 for i in range(n):
1105 squares = [" " for j in range(n)]
1106 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001107 print("|" + "|".join(squares) + "|")
1108 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001109
unknown31569562001-07-04 22:11:22 +00001110# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1111# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1112# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001113# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001114
1115class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001116 def __init__(self, m, n, hard=0):
1117 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001118
Tim Peters9a8c8e22001-07-13 09:12:12 +00001119 # solve() will set up succs[i] to be a list of square #i's
1120 # successors.
1121 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001122
Tim Peters9a8c8e22001-07-13 09:12:12 +00001123 # Remove i0 from each of its successor's successor lists, i.e.
1124 # successors can't go back to i0 again. Return 0 if we can
1125 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001126
Tim Peters9a8c8e22001-07-13 09:12:12 +00001127 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001128 # If we remove all exits from a free square, we're dead:
1129 # even if we move to it next, we can't leave it again.
1130 # If we create a square with one exit, we must visit it next;
1131 # else somebody else will have to visit it, and since there's
1132 # only one adjacent, there won't be a way to leave it again.
1133 # Finelly, if we create more than one free square with a
1134 # single exit, we can only move to one of them next, leaving
1135 # the other one a dead end.
1136 ne0 = ne1 = 0
1137 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001138 s = succs[i]
1139 s.remove(i0)
1140 e = len(s)
1141 if e == 0:
1142 ne0 += 1
1143 elif e == 1:
1144 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001145 return ne0 == 0 and ne1 < 2
1146
Tim Peters9a8c8e22001-07-13 09:12:12 +00001147 # Put i0 back in each of its successor's successor lists.
1148
1149 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001150 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001151 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001152
1153 # Generate the first move.
1154 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001155 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001156 return
1157
unknown31569562001-07-04 22:11:22 +00001158 # Since we're looking for a cycle, it doesn't matter where we
1159 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001160 corner = self.coords2index(0, 0)
1161 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001162 self.lastij = corner
1163 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001164 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001165
1166 # Generate the second moves.
1167 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001168 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001169 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001170 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001171 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001172 assert len(succs[corner]) == 2
1173 assert self.coords2index(1, 2) in succs[corner]
1174 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001175 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001176 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001177 # to (0, 0). Save its index in self.final so that moves before
1178 # the last know it must be kept free.
1179 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001180 this = self.coords2index(i, j)
1181 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001182 self.final = final
unknown31569562001-07-04 22:11:22 +00001183
Tim Peters9a8c8e22001-07-13 09:12:12 +00001184 remove_from_successors(this)
1185 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001186 self.lastij = this
1187 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001188 succs[final].remove(corner)
1189 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001190
Tim Peters9a8c8e22001-07-13 09:12:12 +00001191 # Generate moves 3 thru m*n-1.
1192 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001193 # If some successor has only one exit, must take it.
1194 # Else favor successors with fewer exits.
1195 candidates = []
1196 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 e = len(succs[i])
1198 assert e > 0, "else remove_from_successors() pruning flawed"
1199 if e == 1:
1200 candidates = [(e, i)]
1201 break
1202 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001203 else:
1204 candidates.sort()
1205
1206 for e, i in candidates:
1207 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001208 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001209 self.lastij = i
1210 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001211 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001212
Tim Peters9a8c8e22001-07-13 09:12:12 +00001213 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001214 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001215 # Since the # of backtracking levels is m*n, a poor move early on
1216 # can take eons to undo. Smallest square board for which this
1217 # matters a lot is 52x52.
1218 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001219 # If some successor has only one exit, must take it.
1220 # Else favor successors with fewer exits.
1221 # Break ties via max distance from board centerpoint (favor
1222 # corners and edges whenever possible).
1223 candidates = []
1224 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001225 e = len(succs[i])
1226 assert e > 0, "else remove_from_successors() pruning flawed"
1227 if e == 1:
1228 candidates = [(e, 0, i)]
1229 break
1230 i1, j1 = self.index2coords(i)
1231 d = (i1 - vmid)**2 + (j1 - hmid)**2
1232 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001233 else:
1234 candidates.sort()
1235
1236 for e, d, i in candidates:
1237 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001238 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001239 self.lastij = i
1240 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001241 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001242
1243 # Generate the last move.
1244 def last():
1245 assert self.final in succs[self.lastij]
1246 yield self.final
1247
Tim Peters9a8c8e22001-07-13 09:12:12 +00001248 if m*n < 4:
1249 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001250 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001251 self.squaregenerators = [first, second] + \
1252 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001253 [last]
1254
Tim Peters9a8c8e22001-07-13 09:12:12 +00001255 def coords2index(self, i, j):
1256 assert 0 <= i < self.m
1257 assert 0 <= j < self.n
1258 return i * self.n + j
1259
1260 def index2coords(self, index):
1261 assert 0 <= index < self.m * self.n
1262 return divmod(index, self.n)
1263
1264 def _init_board(self):
1265 succs = self.succs
1266 del succs[:]
1267 m, n = self.m, self.n
1268 c2i = self.coords2index
1269
1270 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1271 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1272 rangen = range(n)
1273 for i in range(m):
1274 for j in rangen:
1275 s = [c2i(i+io, j+jo) for io, jo in offsets
1276 if 0 <= i+io < m and
1277 0 <= j+jo < n]
1278 succs.append(s)
1279
unknown31569562001-07-04 22:11:22 +00001280 # Generate solutions.
1281 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001282 self._init_board()
1283 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001284 yield x
1285
1286 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001287 m, n = self.m, self.n
1288 assert len(x) == m*n
1289 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001290 format = "%" + str(w) + "d"
1291
Tim Peters9a8c8e22001-07-13 09:12:12 +00001292 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001293 k = 1
1294 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001295 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001296 squares[i1][j1] = format % k
1297 k += 1
1298
1299 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001300 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001301 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001302 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001303 print("|" + "|".join(row) + "|")
1304 print(sep)
unknown31569562001-07-04 22:11:22 +00001305
Tim Petersbe4f0a72001-06-29 02:41:16 +00001306conjoin_tests = """
1307
1308Generate the 3-bit binary numbers in order. This illustrates dumbest-
1309possible use of conjoin, just to generate the full cross-product.
1310
unknown31569562001-07-04 22:11:22 +00001311>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001312... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001313[0, 0, 0]
1314[0, 0, 1]
1315[0, 1, 0]
1316[0, 1, 1]
1317[1, 0, 0]
1318[1, 0, 1]
1319[1, 1, 0]
1320[1, 1, 1]
1321
Tim Petersc468fd22001-06-30 07:29:44 +00001322For efficiency in typical backtracking apps, conjoin() yields the same list
1323object each time. So if you want to save away a full account of its
1324generated sequence, you need to copy its results.
1325
1326>>> def gencopy(iterator):
1327... for x in iterator:
1328... yield x[:]
1329
1330>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001331... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001332... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000013330 1 True True
13341 2 True True
13352 4 True True
13363 8 True True
13374 16 True True
13385 32 True True
13396 64 True True
13407 128 True True
13418 256 True True
13429 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001343
Tim Petersbe4f0a72001-06-29 02:41:16 +00001344And run an 8-queens solver.
1345
1346>>> q = Queens(8)
1347>>> LIMIT = 2
1348>>> count = 0
1349>>> for row2col in q.solve():
1350... count += 1
1351... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001352... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001353... q.printsolution(row2col)
1354Solution 1
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+-+-+-+-+-+-+-+-+
1372Solution 2
1373+-+-+-+-+-+-+-+-+
1374|Q| | | | | | | |
1375+-+-+-+-+-+-+-+-+
1376| | | | | |Q| | |
1377+-+-+-+-+-+-+-+-+
1378| | | | | | | |Q|
1379+-+-+-+-+-+-+-+-+
1380| | |Q| | | | | |
1381+-+-+-+-+-+-+-+-+
1382| | | | | | |Q| |
1383+-+-+-+-+-+-+-+-+
1384| | | |Q| | | | |
1385+-+-+-+-+-+-+-+-+
1386| |Q| | | | | | |
1387+-+-+-+-+-+-+-+-+
1388| | | | |Q| | | |
1389+-+-+-+-+-+-+-+-+
1390
Guido van Rossum7131f842007-02-09 20:13:25 +00001391>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000139292 solutions in all.
unknown31569562001-07-04 22:11:22 +00001393
1394And run a Knight's Tour on a 10x10 board. Note that there are about
139520,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1396
Tim Peters9a8c8e22001-07-13 09:12:12 +00001397>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001398>>> LIMIT = 2
1399>>> count = 0
1400>>> for x in k.solve():
1401... count += 1
1402... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001403... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001404... k.printsolution(x)
1405... else:
1406... break
1407Solution 1
1408+---+---+---+---+---+---+---+---+---+---+
1409| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1410+---+---+---+---+---+---+---+---+---+---+
1411| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1412+---+---+---+---+---+---+---+---+---+---+
1413| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1414+---+---+---+---+---+---+---+---+---+---+
1415| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1416+---+---+---+---+---+---+---+---+---+---+
1417| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1418+---+---+---+---+---+---+---+---+---+---+
1419| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1420+---+---+---+---+---+---+---+---+---+---+
1421| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1422+---+---+---+---+---+---+---+---+---+---+
1423| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1424+---+---+---+---+---+---+---+---+---+---+
1425| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1426+---+---+---+---+---+---+---+---+---+---+
1427| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1428+---+---+---+---+---+---+---+---+---+---+
1429Solution 2
1430+---+---+---+---+---+---+---+---+---+---+
1431| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1432+---+---+---+---+---+---+---+---+---+---+
1433| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1434+---+---+---+---+---+---+---+---+---+---+
1435| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1436+---+---+---+---+---+---+---+---+---+---+
1437| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1438+---+---+---+---+---+---+---+---+---+---+
1439| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1440+---+---+---+---+---+---+---+---+---+---+
1441| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1442+---+---+---+---+---+---+---+---+---+---+
1443| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1444+---+---+---+---+---+---+---+---+---+---+
1445| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1446+---+---+---+---+---+---+---+---+---+---+
1447| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1448+---+---+---+---+---+---+---+---+---+---+
1449| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1450+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001451"""
1452
Fred Drake56d12662002-08-09 18:37:10 +00001453weakref_tests = """\
1454Generators are weakly referencable:
1455
1456>>> import weakref
1457>>> def gen():
1458... yield 'foo!'
1459...
1460>>> wr = weakref.ref(gen)
1461>>> wr() is gen
1462True
1463>>> p = weakref.proxy(gen)
1464
1465Generator-iterators are weakly referencable as well:
1466
1467>>> gi = gen()
1468>>> wr = weakref.ref(gi)
1469>>> wr() is gi
1470True
1471>>> p = weakref.proxy(gi)
1472>>> list(p)
1473['foo!']
1474
1475"""
1476
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001477coroutine_tests = """\
1478Sending a value into a started generator:
1479
1480>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001481... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001482... yield 2
1483>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001484>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000014851
1486>>> g.send(42)
148742
14882
1489
1490Sending a value into a new generator produces a TypeError:
1491
1492>>> f().send("foo")
1493Traceback (most recent call last):
1494...
1495TypeError: can't send non-None value to a just-started generator
1496
1497
1498Yield by itself yields None:
1499
1500>>> def f(): yield
1501>>> list(f())
1502[None]
1503
1504
1505
1506An obscene abuse of a yield expression within a generator expression:
1507
1508>>> list((yield 21) for i in range(4))
1509[21, None, 21, None, 21, None, 21, None]
1510
1511And a more sane, but still weird usage:
1512
1513>>> def f(): list(i for i in [(yield 26)])
1514>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001515<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001516
1517
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001518A yield expression with augmented assignment.
1519
1520>>> def coroutine(seq):
1521... count = 0
1522... while count < 200:
1523... count += yield
1524... seq.append(count)
1525>>> seq = []
1526>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001527>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001528>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001529[]
1530>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001531>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001532[10]
1533>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001534>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001535[10, 20]
1536>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001537>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001538[10, 20, 30]
1539
1540
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001541Check some syntax errors for yield expressions:
1542
1543>>> f=lambda: (yield 1),(yield 2)
1544Traceback (most recent call last):
1545 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001546SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001547
1548>>> def f(): return lambda x=(yield): 1
1549Traceback (most recent call last):
1550 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001551SyntaxError: 'return' with argument inside generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001552
1553>>> def f(): x = yield = y
1554Traceback (most recent call last):
1555 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001556SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001557
1558>>> def f(): (yield bar) = y
1559Traceback (most recent call last):
1560 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001561SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001562
1563>>> def f(): (yield bar) += y
1564Traceback (most recent call last):
1565 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001566SyntaxError: augmented assignment to yield expression not possible
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001567
1568
1569Now check some throw() conditions:
1570
1571>>> def f():
1572... while True:
1573... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001574... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001575... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001576... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001577>>> import sys
1578>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001579>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001580
1581>>> g.throw(ValueError) # type only
1582caught ValueError ()
1583
1584>>> g.throw(ValueError("xyz")) # value only
1585caught ValueError (xyz)
1586
1587>>> g.throw(ValueError, ValueError(1)) # value+matching type
1588caught ValueError (1)
1589
1590>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1591caught ValueError (1)
1592
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001593>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1594caught ValueError (1)
1595
Tim Peterse9fe7e02005-08-07 03:04:58 +00001596>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001597Traceback (most recent call last):
1598 ...
1599TypeError: instance exception may not have a separate value
1600
Tim Peterse9fe7e02005-08-07 03:04:58 +00001601>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001602Traceback (most recent call last):
1603 ...
1604TypeError: throw() third argument must be a traceback object
1605
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001606>>> g.throw("abc")
1607Traceback (most recent call last):
1608 ...
1609TypeError: exceptions must be classes or instances deriving from BaseException, not str
1610
1611>>> g.throw(0)
1612Traceback (most recent call last):
1613 ...
1614TypeError: exceptions must be classes or instances deriving from BaseException, not int
1615
1616>>> g.throw(list)
1617Traceback (most recent call last):
1618 ...
1619TypeError: exceptions must be classes or instances deriving from BaseException, not type
1620
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001621>>> def throw(g,exc):
1622... try:
1623... raise exc
1624... except:
1625... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001626>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001627caught ValueError ()
1628
1629>>> g.send(1)
16301
1631
Tim Peterse9fe7e02005-08-07 03:04:58 +00001632>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001633Traceback (most recent call last):
1634 ...
1635TypeError
1636
Guido van Rossum7131f842007-02-09 20:13:25 +00001637>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001638None
1639
1640>>> g.send(2)
1641Traceback (most recent call last):
1642 ...
1643StopIteration
1644
Tim Peterse9fe7e02005-08-07 03:04:58 +00001645>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001646Traceback (most recent call last):
1647 ...
1648ValueError: 6
1649
Tim Peterse9fe7e02005-08-07 03:04:58 +00001650>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001651Traceback (most recent call last):
1652 ...
1653ValueError: 7
1654
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001655Now let's try closing a generator:
1656
1657>>> def f():
1658... try: yield
1659... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00001660... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001661
1662>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001663>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001664>>> g.close()
1665exiting
1666>>> g.close() # should be no-op now
1667
1668>>> f().close() # close on just-opened generator should be fine
1669
Tim Peterse9fe7e02005-08-07 03:04:58 +00001670>>> def f(): yield # an even simpler generator
1671>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001672>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001673>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001674>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001675
1676And finalization:
1677
1678>>> def f():
1679... try: yield
1680... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001681... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001682
1683>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001684>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001685>>> del g
1686exiting
1687
1688
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001689GeneratorExit is not caught by except Exception:
1690
1691>>> def f():
1692... try: yield
1693... except Exception:
1694... print('except')
1695... finally:
1696... print('finally')
1697
1698>>> g = f()
1699>>> next(g)
1700>>> del g
1701finally
1702
1703
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001704Now let's try some ill-behaved generators:
1705
1706>>> def f():
1707... try: yield
1708... except GeneratorExit:
1709... yield "foo!"
1710>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001711>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001712>>> g.close()
1713Traceback (most recent call last):
1714 ...
1715RuntimeError: generator ignored GeneratorExit
1716>>> g.close()
1717
1718
1719Our ill-behaved code should be invoked during GC:
1720
Guido van Rossum34d19282007-08-09 01:03:29 +00001721>>> import sys, io
1722>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001723>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001724>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001725>>> del g
1726>>> sys.stderr.getvalue().startswith(
Neal Norwitz2633c692007-02-26 22:22:47 +00001727... "Exception RuntimeError: 'generator ignored GeneratorExit' in "
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001728... )
1729True
1730>>> sys.stderr = old
1731
1732
1733And errors thrown during closing should propagate:
1734
1735>>> def f():
1736... try: yield
1737... except GeneratorExit:
1738... raise TypeError("fie!")
1739>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001740>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001741>>> g.close()
1742Traceback (most recent call last):
1743 ...
1744TypeError: fie!
1745
1746
1747Ensure that various yield expression constructs make their
1748enclosing function a generator:
1749
1750>>> def f(): x += yield
1751>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001752<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001753
1754>>> def f(): x = yield
1755>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001756<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001757
1758>>> def f(): lambda x=(yield): 1
1759>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001760<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001761
1762>>> def f(): x=(i for i in (yield) if (yield))
1763>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001764<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001765
1766>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1767>>> data = [1,2]
1768>>> g = f(data)
1769>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00001770<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001771>>> g.send(None)
1772'a'
1773>>> data
1774[1, 2]
1775>>> g.send(0)
1776'b'
1777>>> data
1778[27, 2]
1779>>> try: g.send(1)
1780... except StopIteration: pass
1781>>> data
1782[27, 27]
1783
1784"""
1785
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001786refleaks_tests = """
1787Prior to adding cycle-GC support to itertools.tee, this code would leak
1788references. We add it to the standard suite so the routine refleak-tests
1789would trigger if it starts being uncleanable again.
1790
1791>>> import itertools
1792>>> def leak():
1793... class gen:
1794... def __iter__(self):
1795... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00001796... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001797... return self.item
1798... g = gen()
1799... head, tail = itertools.tee(g)
1800... g.item = head
1801... return head
1802>>> it = leak()
1803
1804Make sure to also test the involvement of the tee-internal teedataobject,
1805which stores returned items.
1806
Georg Brandla18af4e2007-04-21 15:47:16 +00001807>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001808
1809
1810
1811This test leaked at one point due to generator finalization/destruction.
1812It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1813was removed.
1814
1815>>> def leak():
1816... def gen():
1817... while True:
1818... yield g
1819... g = gen()
1820
1821>>> leak()
1822
1823
1824
1825This test isn't really generator related, but rather exception-in-cleanup
1826related. The coroutine tests (above) just happen to cause an exception in
1827the generator's __del__ (tp_del) method. We can also test for this
1828explicitly, without generators. We do have to redirect stderr to avoid
1829printing warnings and to doublecheck that we actually tested what we wanted
1830to test.
1831
Guido van Rossum34d19282007-08-09 01:03:29 +00001832>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001833>>> old = sys.stderr
1834>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00001835... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001836... class Leaker:
1837... def __del__(self):
1838... raise RuntimeError
1839...
1840... l = Leaker()
1841... del l
1842... err = sys.stderr.getvalue().strip()
1843... err.startswith(
Neal Norwitz2633c692007-02-26 22:22:47 +00001844... "Exception RuntimeError: RuntimeError() in <"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001845... )
1846... err.endswith("> ignored")
1847... len(err.splitlines())
1848... finally:
1849... sys.stderr = old
1850True
1851True
18521
1853
1854
1855
1856These refleak tests should perhaps be in a testfile of their own,
1857test_generators just happened to be the test that drew these out.
1858
1859"""
1860
Tim Petersf6ed0742001-06-27 07:17:57 +00001861__test__ = {"tut": tutorial_tests,
1862 "pep": pep_tests,
1863 "email": email_tests,
1864 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001865 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001866 "conjoin": conjoin_tests,
1867 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001868 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001869 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001870 }
Tim Peters1def3512001-06-23 20:27:04 +00001871
1872# Magic test name that regrtest.py invokes *after* importing this module.
1873# This worms around a bootstrap problem.
1874# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1875# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001876def test_main(verbose=None):
Barry Warsaw04f357c2002-07-23 19:04:11 +00001877 from test import test_support, test_generators
Tim Peterscca01832004-08-27 15:29:59 +00001878 test_support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001879
1880# This part isn't needed for regrtest, but for running the test directly.
1881if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001882 test_main(1)