blob: f5c1a7d80c97d09b9e53bb14840fae1821d6009b [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 Hettingerc585eec2010-09-07 15:00:15 +0000461merged K into B
462 A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->B L->L M->M
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000463merged A into F
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000464 A->F B->B C->C D->D E->E F->F G->G H->H I->I J->J K->B L->L M->M
465merged E into F
466 A->F B->B C->C D->D E->F F->F G->G H->H I->I J->J K->B L->L M->M
467merged D into C
468 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->J K->B L->L M->M
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000469merged M into C
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000470 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->J K->B L->L M->C
471merged J into B
472 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->B K->B L->L M->C
473merged B into C
474 A->F B->C C->C D->C E->F F->F G->G H->H I->I J->C K->C L->L M->C
475merged F into G
476 A->G B->C C->C D->C E->G F->G G->G H->H I->I J->C K->C L->L M->C
477merged L into C
478 A->G B->C C->C D->C E->G F->G G->G H->H I->I J->C K->C L->C M->C
479merged G into I
480 A->I B->C C->C D->C E->I F->I G->I H->H I->I J->C K->C L->C M->C
481merged I into H
482 A->H B->C C->C D->C E->H F->H G->H H->H I->H J->C K->C L->C M->C
483merged C into H
484 A->H B->H C->H D->H E->H F->H G->H H->H I->H J->H K->H L->H M->H
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
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000731These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000732
733>>> def f():
734... yield 1
735... return
736
Tim Petersaef8cfa2004-08-27 15:12:49 +0000737>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000738... try:
739... yield 1
740... finally:
741... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000742
Tim Petersaef8cfa2004-08-27 15:12:49 +0000743>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000744... try:
745... try:
Tim Peters3caca232001-12-06 06:23:26 +0000746... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000747... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000748... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000749... except:
750... pass
751... finally:
752... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000753
754>>> def f():
755... try:
756... try:
757... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000758... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000759... except ZeroDivisionError:
760... yield 666
761... except:
762... try:
763... x = 12
764... finally:
765... yield 12
766... except:
767... return
768>>> list(f())
769[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000770
771>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000772... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000773>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000774<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000775
Tim Peters08a898f2001-06-28 01:52:22 +0000776
777>>> def f():
778... if 0:
779... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000780>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000781<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000782
Tim Peters08a898f2001-06-28 01:52:22 +0000783
784>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000785... if 0:
786... yield 1
787>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000788<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000789
790>>> def f():
791... if "":
792... yield None
793>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000794<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000795
796>>> def f():
797... return
798... try:
799... if x==4:
800... pass
801... elif 0:
802... try:
Tim Peters3caca232001-12-06 06:23:26 +0000803... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000804... except SyntaxError:
805... pass
806... else:
807... if 0:
808... while 12:
809... x += 1
810... yield 2 # don't blink
811... f(a, b, c, d, e)
812... else:
813... pass
814... except:
815... x = 1
816... return
817>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000818<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000819
820>>> def f():
821... if 0:
822... def g():
823... yield 1
824...
825>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000826<class 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000827
828>>> def f():
829... if 0:
830... class C:
831... def __init__(self):
832... yield 1
833... def f(self):
834... yield 2
835>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000836<class 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000837
838>>> def f():
839... if 0:
840... return
841... if 0:
842... yield 2
843>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000844<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +0000845
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000846This one caused a crash (see SF bug 567538):
847
848>>> def f():
849... for i in range(3):
850... try:
851... continue
852... finally:
853... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000854...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000855>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000856>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008570
Georg Brandla18af4e2007-04-21 15:47:16 +0000858>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008591
Georg Brandla18af4e2007-04-21 15:47:16 +0000860>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00008612
Georg Brandla18af4e2007-04-21 15:47:16 +0000862>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000863Traceback (most recent call last):
864StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +0000865
866
867Test the gi_code attribute
868
869>>> def f():
870... yield 5
871...
872>>> g = f()
873>>> g.gi_code is f.__code__
874True
875>>> next(g)
8765
877>>> next(g)
878Traceback (most recent call last):
879StopIteration
880>>> g.gi_code is f.__code__
881True
882
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000883
884Test the __name__ attribute and the repr()
885
886>>> def f():
887... yield 5
888...
889>>> g = f()
890>>> g.__name__
891'f'
892>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000893'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +0000894
895Lambdas shouldn't have their usual return behavior.
896
897>>> x = lambda: (yield 1)
898>>> list(x())
899[1]
900
901>>> x = lambda: ((yield 1), (yield 2))
902>>> list(x())
903[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +0000904"""
905
Tim Petersbe4f0a72001-06-29 02:41:16 +0000906# conjoin is a simple backtracking generator, named in honor of Icon's
907# "conjunction" control structure. Pass a list of no-argument functions
908# that return iterable objects. Easiest to explain by example: assume the
909# function list [x, y, z] is passed. Then conjoin acts like:
910#
911# def g():
912# values = [None] * 3
913# for values[0] in x():
914# for values[1] in y():
915# for values[2] in z():
916# yield values
917#
918# So some 3-lists of values *may* be generated, each time we successfully
919# get into the innermost loop. If an iterator fails (is exhausted) before
920# then, it "backtracks" to get the next value from the nearest enclosing
921# iterator (the one "to the left"), and starts all over again at the next
922# slot (pumps a fresh iterator). Of course this is most useful when the
923# iterators have side-effects, so that which values *can* be generated at
924# each slot depend on the values iterated at previous slots.
925
Benjamin Peterson78565b22009-06-28 19:19:51 +0000926def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000927
928 values = [None] * len(gs)
929
Benjamin Peterson78565b22009-06-28 19:19:51 +0000930 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000931 if i >= len(gs):
932 yield values
933 else:
934 for values[i] in gs[i]():
935 for x in gen(i+1):
936 yield x
937
938 for x in gen(0):
939 yield x
940
Tim Petersc468fd22001-06-30 07:29:44 +0000941# That works fine, but recursing a level and checking i against len(gs) for
942# each item produced is inefficient. By doing manual loop unrolling across
943# generator boundaries, it's possible to eliminate most of that overhead.
944# This isn't worth the bother *in general* for generators, but conjoin() is
945# a core building block for some CPU-intensive generator applications.
946
947def conjoin(gs):
948
949 n = len(gs)
950 values = [None] * n
951
952 # Do one loop nest at time recursively, until the # of loop nests
953 # remaining is divisible by 3.
954
Benjamin Peterson78565b22009-06-28 19:19:51 +0000955 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +0000956 if i >= n:
957 yield values
958
959 elif (n-i) % 3:
960 ip1 = i+1
961 for values[i] in gs[i]():
962 for x in gen(ip1):
963 yield x
964
965 else:
966 for x in _gen3(i):
967 yield x
968
969 # Do three loop nests at a time, recursing only if at least three more
970 # remain. Don't call directly: this is an internal optimization for
971 # gen's use.
972
Benjamin Peterson78565b22009-06-28 19:19:51 +0000973 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +0000974 assert i < n and (n-i) % 3 == 0
975 ip1, ip2, ip3 = i+1, i+2, i+3
976 g, g1, g2 = gs[i : ip3]
977
978 if ip3 >= n:
979 # These are the last three, so we can yield values directly.
980 for values[i] in g():
981 for values[ip1] in g1():
982 for values[ip2] in g2():
983 yield values
984
985 else:
986 # At least 6 loop nests remain; peel off 3 and recurse for the
987 # rest.
988 for values[i] in g():
989 for values[ip1] in g1():
990 for values[ip2] in g2():
991 for x in _gen3(ip3):
992 yield x
993
994 for x in gen(0):
995 yield x
996
unknown31569562001-07-04 22:11:22 +0000997# And one more approach: For backtracking apps like the Knight's Tour
998# solver below, the number of backtracking levels can be enormous (one
999# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1000# needs 10,000 levels). In such cases Python is likely to run out of
1001# stack space due to recursion. So here's a recursion-free version of
1002# conjoin too.
1003# NOTE WELL: This allows large problems to be solved with only trivial
1004# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001005# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1006# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001007
1008def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1009 n = len(gs)
1010 values = [None] * n
1011 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001012 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001013 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001014 while 1:
1015 # Descend.
1016 try:
1017 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001018 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001019 values[i] = it()
1020 i += 1
1021 except _StopIteration:
1022 pass
unknown31569562001-07-04 22:11:22 +00001023 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001024 assert i == n
1025 yield values
unknown31569562001-07-04 22:11:22 +00001026
Tim Peters9a8c8e22001-07-13 09:12:12 +00001027 # Backtrack until an older iterator can be resumed.
1028 i -= 1
unknown31569562001-07-04 22:11:22 +00001029 while i >= 0:
1030 try:
1031 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001032 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001033 i += 1
1034 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001035 except _StopIteration:
1036 # Continue backtracking.
1037 i -= 1
1038 else:
1039 assert i < 0
1040 break
unknown31569562001-07-04 22:11:22 +00001041
Tim Petersbe4f0a72001-06-29 02:41:16 +00001042# A conjoin-based N-Queens solver.
1043
1044class Queens:
1045 def __init__(self, n):
1046 self.n = n
1047 rangen = range(n)
1048
1049 # Assign a unique int to each column and diagonal.
1050 # columns: n of those, range(n).
1051 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1052 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1053 # based.
1054 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1055 # each, smallest i+j is 0, largest is 2n-2.
1056
1057 # For each square, compute a bit vector of the columns and
1058 # diagonals it covers, and for each row compute a function that
1059 # generates the possiblities for the columns in that row.
1060 self.rowgenerators = []
1061 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001062 rowuses = [(1 << j) | # column ordinal
1063 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1064 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001065 for j in rangen]
1066
1067 def rowgen(rowuses=rowuses):
1068 for j in rangen:
1069 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001070 if uses & self.used == 0:
1071 self.used |= uses
1072 yield j
1073 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001074
1075 self.rowgenerators.append(rowgen)
1076
1077 # Generate solutions.
1078 def solve(self):
1079 self.used = 0
1080 for row2col in conjoin(self.rowgenerators):
1081 yield row2col
1082
1083 def printsolution(self, row2col):
1084 n = self.n
1085 assert n == len(row2col)
1086 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001087 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001088 for i in range(n):
1089 squares = [" " for j in range(n)]
1090 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001091 print("|" + "|".join(squares) + "|")
1092 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001093
unknown31569562001-07-04 22:11:22 +00001094# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1095# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1096# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001097# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001098
1099class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001100 def __init__(self, m, n, hard=0):
1101 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001102
Tim Peters9a8c8e22001-07-13 09:12:12 +00001103 # solve() will set up succs[i] to be a list of square #i's
1104 # successors.
1105 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001106
Tim Peters9a8c8e22001-07-13 09:12:12 +00001107 # Remove i0 from each of its successor's successor lists, i.e.
1108 # successors can't go back to i0 again. Return 0 if we can
1109 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001110
Tim Peters9a8c8e22001-07-13 09:12:12 +00001111 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001112 # If we remove all exits from a free square, we're dead:
1113 # even if we move to it next, we can't leave it again.
1114 # If we create a square with one exit, we must visit it next;
1115 # else somebody else will have to visit it, and since there's
1116 # only one adjacent, there won't be a way to leave it again.
1117 # Finelly, if we create more than one free square with a
1118 # single exit, we can only move to one of them next, leaving
1119 # the other one a dead end.
1120 ne0 = ne1 = 0
1121 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001122 s = succs[i]
1123 s.remove(i0)
1124 e = len(s)
1125 if e == 0:
1126 ne0 += 1
1127 elif e == 1:
1128 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001129 return ne0 == 0 and ne1 < 2
1130
Tim Peters9a8c8e22001-07-13 09:12:12 +00001131 # Put i0 back in each of its successor's successor lists.
1132
1133 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001134 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001135 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001136
1137 # Generate the first move.
1138 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001139 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001140 return
1141
unknown31569562001-07-04 22:11:22 +00001142 # Since we're looking for a cycle, it doesn't matter where we
1143 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001144 corner = self.coords2index(0, 0)
1145 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001146 self.lastij = corner
1147 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001148 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001149
1150 # Generate the second moves.
1151 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001152 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001153 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001154 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001155 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001156 assert len(succs[corner]) == 2
1157 assert self.coords2index(1, 2) in succs[corner]
1158 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001159 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001160 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001161 # to (0, 0). Save its index in self.final so that moves before
1162 # the last know it must be kept free.
1163 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001164 this = self.coords2index(i, j)
1165 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001166 self.final = final
unknown31569562001-07-04 22:11:22 +00001167
Tim Peters9a8c8e22001-07-13 09:12:12 +00001168 remove_from_successors(this)
1169 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001170 self.lastij = this
1171 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001172 succs[final].remove(corner)
1173 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001174
Tim Peters9a8c8e22001-07-13 09:12:12 +00001175 # Generate moves 3 thru m*n-1.
1176 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001177 # If some successor has only one exit, must take it.
1178 # Else favor successors with fewer exits.
1179 candidates = []
1180 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001181 e = len(succs[i])
1182 assert e > 0, "else remove_from_successors() pruning flawed"
1183 if e == 1:
1184 candidates = [(e, i)]
1185 break
1186 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001187 else:
1188 candidates.sort()
1189
1190 for e, i in candidates:
1191 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001192 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001193 self.lastij = i
1194 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001195 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001196
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001198 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001199 # Since the # of backtracking levels is m*n, a poor move early on
1200 # can take eons to undo. Smallest square board for which this
1201 # matters a lot is 52x52.
1202 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001203 # If some successor has only one exit, must take it.
1204 # Else favor successors with fewer exits.
1205 # Break ties via max distance from board centerpoint (favor
1206 # corners and edges whenever possible).
1207 candidates = []
1208 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001209 e = len(succs[i])
1210 assert e > 0, "else remove_from_successors() pruning flawed"
1211 if e == 1:
1212 candidates = [(e, 0, i)]
1213 break
1214 i1, j1 = self.index2coords(i)
1215 d = (i1 - vmid)**2 + (j1 - hmid)**2
1216 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001217 else:
1218 candidates.sort()
1219
1220 for e, d, i in candidates:
1221 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001222 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001223 self.lastij = i
1224 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001225 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001226
1227 # Generate the last move.
1228 def last():
1229 assert self.final in succs[self.lastij]
1230 yield self.final
1231
Tim Peters9a8c8e22001-07-13 09:12:12 +00001232 if m*n < 4:
1233 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001234 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001235 self.squaregenerators = [first, second] + \
1236 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001237 [last]
1238
Tim Peters9a8c8e22001-07-13 09:12:12 +00001239 def coords2index(self, i, j):
1240 assert 0 <= i < self.m
1241 assert 0 <= j < self.n
1242 return i * self.n + j
1243
1244 def index2coords(self, index):
1245 assert 0 <= index < self.m * self.n
1246 return divmod(index, self.n)
1247
1248 def _init_board(self):
1249 succs = self.succs
1250 del succs[:]
1251 m, n = self.m, self.n
1252 c2i = self.coords2index
1253
1254 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1255 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1256 rangen = range(n)
1257 for i in range(m):
1258 for j in rangen:
1259 s = [c2i(i+io, j+jo) for io, jo in offsets
1260 if 0 <= i+io < m and
1261 0 <= j+jo < n]
1262 succs.append(s)
1263
unknown31569562001-07-04 22:11:22 +00001264 # Generate solutions.
1265 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001266 self._init_board()
1267 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001268 yield x
1269
1270 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001271 m, n = self.m, self.n
1272 assert len(x) == m*n
1273 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001274 format = "%" + str(w) + "d"
1275
Tim Peters9a8c8e22001-07-13 09:12:12 +00001276 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001277 k = 1
1278 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001279 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001280 squares[i1][j1] = format % k
1281 k += 1
1282
1283 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001284 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001285 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001286 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001287 print("|" + "|".join(row) + "|")
1288 print(sep)
unknown31569562001-07-04 22:11:22 +00001289
Tim Petersbe4f0a72001-06-29 02:41:16 +00001290conjoin_tests = """
1291
1292Generate the 3-bit binary numbers in order. This illustrates dumbest-
1293possible use of conjoin, just to generate the full cross-product.
1294
unknown31569562001-07-04 22:11:22 +00001295>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001296... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001297[0, 0, 0]
1298[0, 0, 1]
1299[0, 1, 0]
1300[0, 1, 1]
1301[1, 0, 0]
1302[1, 0, 1]
1303[1, 1, 0]
1304[1, 1, 1]
1305
Tim Petersc468fd22001-06-30 07:29:44 +00001306For efficiency in typical backtracking apps, conjoin() yields the same list
1307object each time. So if you want to save away a full account of its
1308generated sequence, you need to copy its results.
1309
1310>>> def gencopy(iterator):
1311... for x in iterator:
1312... yield x[:]
1313
1314>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001315... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001316... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000013170 1 True True
13181 2 True True
13192 4 True True
13203 8 True True
13214 16 True True
13225 32 True True
13236 64 True True
13247 128 True True
13258 256 True True
13269 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001327
Tim Petersbe4f0a72001-06-29 02:41:16 +00001328And run an 8-queens solver.
1329
1330>>> q = Queens(8)
1331>>> LIMIT = 2
1332>>> count = 0
1333>>> for row2col in q.solve():
1334... count += 1
1335... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001336... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001337... q.printsolution(row2col)
1338Solution 1
1339+-+-+-+-+-+-+-+-+
1340|Q| | | | | | | |
1341+-+-+-+-+-+-+-+-+
1342| | | | |Q| | | |
1343+-+-+-+-+-+-+-+-+
1344| | | | | | | |Q|
1345+-+-+-+-+-+-+-+-+
1346| | | | | |Q| | |
1347+-+-+-+-+-+-+-+-+
1348| | |Q| | | | | |
1349+-+-+-+-+-+-+-+-+
1350| | | | | | |Q| |
1351+-+-+-+-+-+-+-+-+
1352| |Q| | | | | | |
1353+-+-+-+-+-+-+-+-+
1354| | | |Q| | | | |
1355+-+-+-+-+-+-+-+-+
1356Solution 2
1357+-+-+-+-+-+-+-+-+
1358|Q| | | | | | | |
1359+-+-+-+-+-+-+-+-+
1360| | | | | |Q| | |
1361+-+-+-+-+-+-+-+-+
1362| | | | | | | |Q|
1363+-+-+-+-+-+-+-+-+
1364| | |Q| | | | | |
1365+-+-+-+-+-+-+-+-+
1366| | | | | | |Q| |
1367+-+-+-+-+-+-+-+-+
1368| | | |Q| | | | |
1369+-+-+-+-+-+-+-+-+
1370| |Q| | | | | | |
1371+-+-+-+-+-+-+-+-+
1372| | | | |Q| | | |
1373+-+-+-+-+-+-+-+-+
1374
Guido van Rossum7131f842007-02-09 20:13:25 +00001375>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000137692 solutions in all.
unknown31569562001-07-04 22:11:22 +00001377
1378And run a Knight's Tour on a 10x10 board. Note that there are about
137920,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1380
Tim Peters9a8c8e22001-07-13 09:12:12 +00001381>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001382>>> LIMIT = 2
1383>>> count = 0
1384>>> for x in k.solve():
1385... count += 1
1386... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001387... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001388... k.printsolution(x)
1389... else:
1390... break
1391Solution 1
1392+---+---+---+---+---+---+---+---+---+---+
1393| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1394+---+---+---+---+---+---+---+---+---+---+
1395| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1396+---+---+---+---+---+---+---+---+---+---+
1397| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1398+---+---+---+---+---+---+---+---+---+---+
1399| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1400+---+---+---+---+---+---+---+---+---+---+
1401| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1402+---+---+---+---+---+---+---+---+---+---+
1403| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1404+---+---+---+---+---+---+---+---+---+---+
1405| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1406+---+---+---+---+---+---+---+---+---+---+
1407| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1408+---+---+---+---+---+---+---+---+---+---+
1409| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1410+---+---+---+---+---+---+---+---+---+---+
1411| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1412+---+---+---+---+---+---+---+---+---+---+
1413Solution 2
1414+---+---+---+---+---+---+---+---+---+---+
1415| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1416+---+---+---+---+---+---+---+---+---+---+
1417| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1418+---+---+---+---+---+---+---+---+---+---+
1419| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1420+---+---+---+---+---+---+---+---+---+---+
1421| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1422+---+---+---+---+---+---+---+---+---+---+
1423| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1424+---+---+---+---+---+---+---+---+---+---+
1425| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1426+---+---+---+---+---+---+---+---+---+---+
1427| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1428+---+---+---+---+---+---+---+---+---+---+
1429| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1430+---+---+---+---+---+---+---+---+---+---+
1431| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1432+---+---+---+---+---+---+---+---+---+---+
1433| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1434+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001435"""
1436
Fred Drake56d12662002-08-09 18:37:10 +00001437weakref_tests = """\
1438Generators are weakly referencable:
1439
1440>>> import weakref
1441>>> def gen():
1442... yield 'foo!'
1443...
1444>>> wr = weakref.ref(gen)
1445>>> wr() is gen
1446True
1447>>> p = weakref.proxy(gen)
1448
1449Generator-iterators are weakly referencable as well:
1450
1451>>> gi = gen()
1452>>> wr = weakref.ref(gi)
1453>>> wr() is gi
1454True
1455>>> p = weakref.proxy(gi)
1456>>> list(p)
1457['foo!']
1458
1459"""
1460
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001461coroutine_tests = """\
1462Sending a value into a started generator:
1463
1464>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001465... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001466... yield 2
1467>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001468>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000014691
1470>>> g.send(42)
147142
14722
1473
1474Sending a value into a new generator produces a TypeError:
1475
1476>>> f().send("foo")
1477Traceback (most recent call last):
1478...
1479TypeError: can't send non-None value to a just-started generator
1480
1481
1482Yield by itself yields None:
1483
1484>>> def f(): yield
1485>>> list(f())
1486[None]
1487
1488
1489
1490An obscene abuse of a yield expression within a generator expression:
1491
1492>>> list((yield 21) for i in range(4))
1493[21, None, 21, None, 21, None, 21, None]
1494
1495And a more sane, but still weird usage:
1496
1497>>> def f(): list(i for i in [(yield 26)])
1498>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001499<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001500
1501
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001502A yield expression with augmented assignment.
1503
1504>>> def coroutine(seq):
1505... count = 0
1506... while count < 200:
1507... count += yield
1508... seq.append(count)
1509>>> seq = []
1510>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001511>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001512>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001513[]
1514>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001515>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001516[10]
1517>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001518>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001519[10, 20]
1520>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001521>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001522[10, 20, 30]
1523
1524
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001525Check some syntax errors for yield expressions:
1526
1527>>> f=lambda: (yield 1),(yield 2)
1528Traceback (most recent call last):
1529 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001530SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001531
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001532>>> def f(): x = yield = y
1533Traceback (most recent call last):
1534 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001535SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001536
1537>>> def f(): (yield bar) = y
1538Traceback (most recent call last):
1539 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001540SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001541
1542>>> def f(): (yield bar) += y
1543Traceback (most recent call last):
1544 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001545SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001546
1547
1548Now check some throw() conditions:
1549
1550>>> def f():
1551... while True:
1552... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001553... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001554... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001555... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001556>>> import sys
1557>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001558>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001559
1560>>> g.throw(ValueError) # type only
1561caught ValueError ()
1562
1563>>> g.throw(ValueError("xyz")) # value only
1564caught ValueError (xyz)
1565
1566>>> g.throw(ValueError, ValueError(1)) # value+matching type
1567caught ValueError (1)
1568
1569>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1570caught ValueError (1)
1571
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001572>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1573caught ValueError (1)
1574
Tim Peterse9fe7e02005-08-07 03:04:58 +00001575>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001576Traceback (most recent call last):
1577 ...
1578TypeError: instance exception may not have a separate value
1579
Tim Peterse9fe7e02005-08-07 03:04:58 +00001580>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001581Traceback (most recent call last):
1582 ...
1583TypeError: throw() third argument must be a traceback object
1584
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001585>>> g.throw("abc")
1586Traceback (most recent call last):
1587 ...
1588TypeError: exceptions must be classes or instances deriving from BaseException, not str
1589
1590>>> g.throw(0)
1591Traceback (most recent call last):
1592 ...
1593TypeError: exceptions must be classes or instances deriving from BaseException, not int
1594
1595>>> g.throw(list)
1596Traceback (most recent call last):
1597 ...
1598TypeError: exceptions must be classes or instances deriving from BaseException, not type
1599
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001600>>> def throw(g,exc):
1601... try:
1602... raise exc
1603... except:
1604... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001605>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001606caught ValueError ()
1607
1608>>> g.send(1)
16091
1610
Tim Peterse9fe7e02005-08-07 03:04:58 +00001611>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001612Traceback (most recent call last):
1613 ...
1614TypeError
1615
Guido van Rossum7131f842007-02-09 20:13:25 +00001616>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001617None
1618
1619>>> g.send(2)
1620Traceback (most recent call last):
1621 ...
1622StopIteration
1623
Tim Peterse9fe7e02005-08-07 03:04:58 +00001624>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001625Traceback (most recent call last):
1626 ...
1627ValueError: 6
1628
Tim Peterse9fe7e02005-08-07 03:04:58 +00001629>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001630Traceback (most recent call last):
1631 ...
1632ValueError: 7
1633
Antoine Pitrou551ba202011-10-18 16:40:50 +02001634Plain "raise" inside a generator should preserve the traceback (#13188).
1635The traceback should have 3 levels:
1636- g.throw()
1637- f()
1638- 1/0
1639
1640>>> def f():
1641... try:
1642... yield
1643... except:
1644... raise
1645>>> g = f()
1646>>> try:
1647... 1/0
1648... except ZeroDivisionError as v:
1649... try:
1650... g.throw(v)
1651... except Exception as w:
1652... tb = w.__traceback__
1653>>> levels = 0
1654>>> while tb:
1655... levels += 1
1656... tb = tb.tb_next
1657>>> levels
16583
1659
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001660Now let's try closing a generator:
1661
1662>>> def f():
1663... try: yield
1664... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00001665... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001666
1667>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001668>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001669>>> g.close()
1670exiting
1671>>> g.close() # should be no-op now
1672
1673>>> f().close() # close on just-opened generator should be fine
1674
Tim Peterse9fe7e02005-08-07 03:04:58 +00001675>>> def f(): yield # an even simpler generator
1676>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001677>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001678>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001679>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001680
1681And finalization:
1682
1683>>> def f():
1684... try: yield
1685... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001686... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001687
1688>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001689>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001690>>> del g
1691exiting
1692
1693
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001694GeneratorExit is not caught by except Exception:
1695
1696>>> def f():
1697... try: yield
1698... except Exception:
1699... print('except')
1700... finally:
1701... print('finally')
1702
1703>>> g = f()
1704>>> next(g)
1705>>> del g
1706finally
1707
1708
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001709Now let's try some ill-behaved generators:
1710
1711>>> def f():
1712... try: yield
1713... except GeneratorExit:
1714... yield "foo!"
1715>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001716>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001717>>> g.close()
1718Traceback (most recent call last):
1719 ...
1720RuntimeError: generator ignored GeneratorExit
1721>>> g.close()
1722
1723
1724Our ill-behaved code should be invoked during GC:
1725
Guido van Rossum34d19282007-08-09 01:03:29 +00001726>>> import sys, io
1727>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001728>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001729>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001730>>> del g
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001731>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001732True
1733>>> sys.stderr = old
1734
1735
1736And errors thrown during closing should propagate:
1737
1738>>> def f():
1739... try: yield
1740... except GeneratorExit:
1741... raise TypeError("fie!")
1742>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001743>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001744>>> g.close()
1745Traceback (most recent call last):
1746 ...
1747TypeError: fie!
1748
1749
1750Ensure that various yield expression constructs make their
1751enclosing function a generator:
1752
1753>>> def f(): x += yield
1754>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001755<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001756
1757>>> def f(): x = yield
1758>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001759<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001760
1761>>> def f(): lambda x=(yield): 1
1762>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001763<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001764
1765>>> def f(): x=(i for i in (yield) if (yield))
1766>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001767<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001768
1769>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1770>>> data = [1,2]
1771>>> g = f(data)
1772>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00001773<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001774>>> g.send(None)
1775'a'
1776>>> data
1777[1, 2]
1778>>> g.send(0)
1779'b'
1780>>> data
1781[27, 2]
1782>>> try: g.send(1)
1783... except StopIteration: pass
1784>>> data
1785[27, 27]
1786
1787"""
1788
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001789refleaks_tests = """
1790Prior to adding cycle-GC support to itertools.tee, this code would leak
1791references. We add it to the standard suite so the routine refleak-tests
1792would trigger if it starts being uncleanable again.
1793
1794>>> import itertools
1795>>> def leak():
1796... class gen:
1797... def __iter__(self):
1798... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00001799... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001800... return self.item
1801... g = gen()
1802... head, tail = itertools.tee(g)
1803... g.item = head
1804... return head
1805>>> it = leak()
1806
1807Make sure to also test the involvement of the tee-internal teedataobject,
1808which stores returned items.
1809
Georg Brandla18af4e2007-04-21 15:47:16 +00001810>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001811
1812
1813
1814This test leaked at one point due to generator finalization/destruction.
1815It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1816was removed.
1817
1818>>> def leak():
1819... def gen():
1820... while True:
1821... yield g
1822... g = gen()
1823
1824>>> leak()
1825
1826
1827
1828This test isn't really generator related, but rather exception-in-cleanup
1829related. The coroutine tests (above) just happen to cause an exception in
1830the generator's __del__ (tp_del) method. We can also test for this
1831explicitly, without generators. We do have to redirect stderr to avoid
1832printing warnings and to doublecheck that we actually tested what we wanted
1833to test.
1834
Guido van Rossum34d19282007-08-09 01:03:29 +00001835>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001836>>> old = sys.stderr
1837>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00001838... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001839... class Leaker:
1840... def __del__(self):
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001841... def invoke(message):
1842... raise RuntimeError(message)
1843... invoke("test")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001844...
1845... l = Leaker()
1846... del l
1847... err = sys.stderr.getvalue().strip()
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001848... "Exception ignored in" in err
1849... "RuntimeError: test" in err
1850... "Traceback" in err
1851... "in invoke" in err
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001852... finally:
1853... sys.stderr = old
1854True
1855True
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001856True
1857True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001858
1859
1860These refleak tests should perhaps be in a testfile of their own,
1861test_generators just happened to be the test that drew these out.
1862
1863"""
1864
Tim Petersf6ed0742001-06-27 07:17:57 +00001865__test__ = {"tut": tutorial_tests,
1866 "pep": pep_tests,
1867 "email": email_tests,
1868 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001869 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001870 "conjoin": conjoin_tests,
1871 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001872 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001873 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001874 }
Tim Peters1def3512001-06-23 20:27:04 +00001875
1876# Magic test name that regrtest.py invokes *after* importing this module.
1877# This worms around a bootstrap problem.
1878# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1879# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001880def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001881 from test import support, test_generators
1882 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001883
1884# This part isn't needed for regrtest, but for running the test directly.
1885if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001886 test_main(1)