blob: 90af15bed508affe298c4539607f5db5acc2e2fa [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
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000920
921Test the __name__ attribute and the repr()
922
923>>> def f():
924... yield 5
925...
926>>> g = f()
927>>> g.__name__
928'f'
929>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000930'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +0000931
932Lambdas shouldn't have their usual return behavior.
933
934>>> x = lambda: (yield 1)
935>>> list(x())
936[1]
937
938>>> x = lambda: ((yield 1), (yield 2))
939>>> list(x())
940[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +0000941"""
942
Tim Petersbe4f0a72001-06-29 02:41:16 +0000943# conjoin is a simple backtracking generator, named in honor of Icon's
944# "conjunction" control structure. Pass a list of no-argument functions
945# that return iterable objects. Easiest to explain by example: assume the
946# function list [x, y, z] is passed. Then conjoin acts like:
947#
948# def g():
949# values = [None] * 3
950# for values[0] in x():
951# for values[1] in y():
952# for values[2] in z():
953# yield values
954#
955# So some 3-lists of values *may* be generated, each time we successfully
956# get into the innermost loop. If an iterator fails (is exhausted) before
957# then, it "backtracks" to get the next value from the nearest enclosing
958# iterator (the one "to the left"), and starts all over again at the next
959# slot (pumps a fresh iterator). Of course this is most useful when the
960# iterators have side-effects, so that which values *can* be generated at
961# each slot depend on the values iterated at previous slots.
962
Benjamin Peterson78565b22009-06-28 19:19:51 +0000963def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000964
965 values = [None] * len(gs)
966
Benjamin Peterson78565b22009-06-28 19:19:51 +0000967 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000968 if i >= len(gs):
969 yield values
970 else:
971 for values[i] in gs[i]():
972 for x in gen(i+1):
973 yield x
974
975 for x in gen(0):
976 yield x
977
Tim Petersc468fd22001-06-30 07:29:44 +0000978# That works fine, but recursing a level and checking i against len(gs) for
979# each item produced is inefficient. By doing manual loop unrolling across
980# generator boundaries, it's possible to eliminate most of that overhead.
981# This isn't worth the bother *in general* for generators, but conjoin() is
982# a core building block for some CPU-intensive generator applications.
983
984def conjoin(gs):
985
986 n = len(gs)
987 values = [None] * n
988
989 # Do one loop nest at time recursively, until the # of loop nests
990 # remaining is divisible by 3.
991
Benjamin Peterson78565b22009-06-28 19:19:51 +0000992 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +0000993 if i >= n:
994 yield values
995
996 elif (n-i) % 3:
997 ip1 = i+1
998 for values[i] in gs[i]():
999 for x in gen(ip1):
1000 yield x
1001
1002 else:
1003 for x in _gen3(i):
1004 yield x
1005
1006 # Do three loop nests at a time, recursing only if at least three more
1007 # remain. Don't call directly: this is an internal optimization for
1008 # gen's use.
1009
Benjamin Peterson78565b22009-06-28 19:19:51 +00001010 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001011 assert i < n and (n-i) % 3 == 0
1012 ip1, ip2, ip3 = i+1, i+2, i+3
1013 g, g1, g2 = gs[i : ip3]
1014
1015 if ip3 >= n:
1016 # These are the last three, so we can yield values directly.
1017 for values[i] in g():
1018 for values[ip1] in g1():
1019 for values[ip2] in g2():
1020 yield values
1021
1022 else:
1023 # At least 6 loop nests remain; peel off 3 and recurse for the
1024 # rest.
1025 for values[i] in g():
1026 for values[ip1] in g1():
1027 for values[ip2] in g2():
1028 for x in _gen3(ip3):
1029 yield x
1030
1031 for x in gen(0):
1032 yield x
1033
unknown31569562001-07-04 22:11:22 +00001034# And one more approach: For backtracking apps like the Knight's Tour
1035# solver below, the number of backtracking levels can be enormous (one
1036# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1037# needs 10,000 levels). In such cases Python is likely to run out of
1038# stack space due to recursion. So here's a recursion-free version of
1039# conjoin too.
1040# NOTE WELL: This allows large problems to be solved with only trivial
1041# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001042# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1043# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001044
1045def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1046 n = len(gs)
1047 values = [None] * n
1048 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001049 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001050 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001051 while 1:
1052 # Descend.
1053 try:
1054 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001055 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001056 values[i] = it()
1057 i += 1
1058 except _StopIteration:
1059 pass
unknown31569562001-07-04 22:11:22 +00001060 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001061 assert i == n
1062 yield values
unknown31569562001-07-04 22:11:22 +00001063
Tim Peters9a8c8e22001-07-13 09:12:12 +00001064 # Backtrack until an older iterator can be resumed.
1065 i -= 1
unknown31569562001-07-04 22:11:22 +00001066 while i >= 0:
1067 try:
1068 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001069 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001070 i += 1
1071 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001072 except _StopIteration:
1073 # Continue backtracking.
1074 i -= 1
1075 else:
1076 assert i < 0
1077 break
unknown31569562001-07-04 22:11:22 +00001078
Tim Petersbe4f0a72001-06-29 02:41:16 +00001079# A conjoin-based N-Queens solver.
1080
1081class Queens:
1082 def __init__(self, n):
1083 self.n = n
1084 rangen = range(n)
1085
1086 # Assign a unique int to each column and diagonal.
1087 # columns: n of those, range(n).
1088 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1089 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1090 # based.
1091 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1092 # each, smallest i+j is 0, largest is 2n-2.
1093
1094 # For each square, compute a bit vector of the columns and
1095 # diagonals it covers, and for each row compute a function that
1096 # generates the possiblities for the columns in that row.
1097 self.rowgenerators = []
1098 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001099 rowuses = [(1 << j) | # column ordinal
1100 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1101 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001102 for j in rangen]
1103
1104 def rowgen(rowuses=rowuses):
1105 for j in rangen:
1106 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001107 if uses & self.used == 0:
1108 self.used |= uses
1109 yield j
1110 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001111
1112 self.rowgenerators.append(rowgen)
1113
1114 # Generate solutions.
1115 def solve(self):
1116 self.used = 0
1117 for row2col in conjoin(self.rowgenerators):
1118 yield row2col
1119
1120 def printsolution(self, row2col):
1121 n = self.n
1122 assert n == len(row2col)
1123 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001124 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001125 for i in range(n):
1126 squares = [" " for j in range(n)]
1127 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001128 print("|" + "|".join(squares) + "|")
1129 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001130
unknown31569562001-07-04 22:11:22 +00001131# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1132# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1133# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001134# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001135
1136class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001137 def __init__(self, m, n, hard=0):
1138 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001139
Tim Peters9a8c8e22001-07-13 09:12:12 +00001140 # solve() will set up succs[i] to be a list of square #i's
1141 # successors.
1142 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001143
Tim Peters9a8c8e22001-07-13 09:12:12 +00001144 # Remove i0 from each of its successor's successor lists, i.e.
1145 # successors can't go back to i0 again. Return 0 if we can
1146 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001147
Tim Peters9a8c8e22001-07-13 09:12:12 +00001148 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001149 # If we remove all exits from a free square, we're dead:
1150 # even if we move to it next, we can't leave it again.
1151 # If we create a square with one exit, we must visit it next;
1152 # else somebody else will have to visit it, and since there's
1153 # only one adjacent, there won't be a way to leave it again.
1154 # Finelly, if we create more than one free square with a
1155 # single exit, we can only move to one of them next, leaving
1156 # the other one a dead end.
1157 ne0 = ne1 = 0
1158 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001159 s = succs[i]
1160 s.remove(i0)
1161 e = len(s)
1162 if e == 0:
1163 ne0 += 1
1164 elif e == 1:
1165 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001166 return ne0 == 0 and ne1 < 2
1167
Tim Peters9a8c8e22001-07-13 09:12:12 +00001168 # Put i0 back in each of its successor's successor lists.
1169
1170 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001171 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001172 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001173
1174 # Generate the first move.
1175 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001176 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001177 return
1178
unknown31569562001-07-04 22:11:22 +00001179 # Since we're looking for a cycle, it doesn't matter where we
1180 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001181 corner = self.coords2index(0, 0)
1182 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001183 self.lastij = corner
1184 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001185 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001186
1187 # Generate the second moves.
1188 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001189 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001190 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001191 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001192 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001193 assert len(succs[corner]) == 2
1194 assert self.coords2index(1, 2) in succs[corner]
1195 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001196 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001198 # to (0, 0). Save its index in self.final so that moves before
1199 # the last know it must be kept free.
1200 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001201 this = self.coords2index(i, j)
1202 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001203 self.final = final
unknown31569562001-07-04 22:11:22 +00001204
Tim Peters9a8c8e22001-07-13 09:12:12 +00001205 remove_from_successors(this)
1206 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001207 self.lastij = this
1208 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001209 succs[final].remove(corner)
1210 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001211
Tim Peters9a8c8e22001-07-13 09:12:12 +00001212 # Generate moves 3 thru m*n-1.
1213 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001214 # If some successor has only one exit, must take it.
1215 # Else favor successors with fewer exits.
1216 candidates = []
1217 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001218 e = len(succs[i])
1219 assert e > 0, "else remove_from_successors() pruning flawed"
1220 if e == 1:
1221 candidates = [(e, i)]
1222 break
1223 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001224 else:
1225 candidates.sort()
1226
1227 for e, i in candidates:
1228 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001229 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001230 self.lastij = i
1231 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001232 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001233
Tim Peters9a8c8e22001-07-13 09:12:12 +00001234 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001235 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001236 # Since the # of backtracking levels is m*n, a poor move early on
1237 # can take eons to undo. Smallest square board for which this
1238 # matters a lot is 52x52.
1239 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001240 # If some successor has only one exit, must take it.
1241 # Else favor successors with fewer exits.
1242 # Break ties via max distance from board centerpoint (favor
1243 # corners and edges whenever possible).
1244 candidates = []
1245 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001246 e = len(succs[i])
1247 assert e > 0, "else remove_from_successors() pruning flawed"
1248 if e == 1:
1249 candidates = [(e, 0, i)]
1250 break
1251 i1, j1 = self.index2coords(i)
1252 d = (i1 - vmid)**2 + (j1 - hmid)**2
1253 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001254 else:
1255 candidates.sort()
1256
1257 for e, d, i in candidates:
1258 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001259 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001260 self.lastij = i
1261 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001262 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001263
1264 # Generate the last move.
1265 def last():
1266 assert self.final in succs[self.lastij]
1267 yield self.final
1268
Tim Peters9a8c8e22001-07-13 09:12:12 +00001269 if m*n < 4:
1270 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001271 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001272 self.squaregenerators = [first, second] + \
1273 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001274 [last]
1275
Tim Peters9a8c8e22001-07-13 09:12:12 +00001276 def coords2index(self, i, j):
1277 assert 0 <= i < self.m
1278 assert 0 <= j < self.n
1279 return i * self.n + j
1280
1281 def index2coords(self, index):
1282 assert 0 <= index < self.m * self.n
1283 return divmod(index, self.n)
1284
1285 def _init_board(self):
1286 succs = self.succs
1287 del succs[:]
1288 m, n = self.m, self.n
1289 c2i = self.coords2index
1290
1291 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1292 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1293 rangen = range(n)
1294 for i in range(m):
1295 for j in rangen:
1296 s = [c2i(i+io, j+jo) for io, jo in offsets
1297 if 0 <= i+io < m and
1298 0 <= j+jo < n]
1299 succs.append(s)
1300
unknown31569562001-07-04 22:11:22 +00001301 # Generate solutions.
1302 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001303 self._init_board()
1304 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001305 yield x
1306
1307 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001308 m, n = self.m, self.n
1309 assert len(x) == m*n
1310 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001311 format = "%" + str(w) + "d"
1312
Tim Peters9a8c8e22001-07-13 09:12:12 +00001313 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001314 k = 1
1315 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001316 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001317 squares[i1][j1] = format % k
1318 k += 1
1319
1320 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001321 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001322 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001323 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001324 print("|" + "|".join(row) + "|")
1325 print(sep)
unknown31569562001-07-04 22:11:22 +00001326
Tim Petersbe4f0a72001-06-29 02:41:16 +00001327conjoin_tests = """
1328
1329Generate the 3-bit binary numbers in order. This illustrates dumbest-
1330possible use of conjoin, just to generate the full cross-product.
1331
unknown31569562001-07-04 22:11:22 +00001332>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001333... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001334[0, 0, 0]
1335[0, 0, 1]
1336[0, 1, 0]
1337[0, 1, 1]
1338[1, 0, 0]
1339[1, 0, 1]
1340[1, 1, 0]
1341[1, 1, 1]
1342
Tim Petersc468fd22001-06-30 07:29:44 +00001343For efficiency in typical backtracking apps, conjoin() yields the same list
1344object each time. So if you want to save away a full account of its
1345generated sequence, you need to copy its results.
1346
1347>>> def gencopy(iterator):
1348... for x in iterator:
1349... yield x[:]
1350
1351>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001352... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001353... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000013540 1 True True
13551 2 True True
13562 4 True True
13573 8 True True
13584 16 True True
13595 32 True True
13606 64 True True
13617 128 True True
13628 256 True True
13639 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001364
Tim Petersbe4f0a72001-06-29 02:41:16 +00001365And run an 8-queens solver.
1366
1367>>> q = Queens(8)
1368>>> LIMIT = 2
1369>>> count = 0
1370>>> for row2col in q.solve():
1371... count += 1
1372... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001373... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001374... q.printsolution(row2col)
1375Solution 1
1376+-+-+-+-+-+-+-+-+
1377|Q| | | | | | | |
1378+-+-+-+-+-+-+-+-+
1379| | | | |Q| | | |
1380+-+-+-+-+-+-+-+-+
1381| | | | | | | |Q|
1382+-+-+-+-+-+-+-+-+
1383| | | | | |Q| | |
1384+-+-+-+-+-+-+-+-+
1385| | |Q| | | | | |
1386+-+-+-+-+-+-+-+-+
1387| | | | | | |Q| |
1388+-+-+-+-+-+-+-+-+
1389| |Q| | | | | | |
1390+-+-+-+-+-+-+-+-+
1391| | | |Q| | | | |
1392+-+-+-+-+-+-+-+-+
1393Solution 2
1394+-+-+-+-+-+-+-+-+
1395|Q| | | | | | | |
1396+-+-+-+-+-+-+-+-+
1397| | | | | |Q| | |
1398+-+-+-+-+-+-+-+-+
1399| | | | | | | |Q|
1400+-+-+-+-+-+-+-+-+
1401| | |Q| | | | | |
1402+-+-+-+-+-+-+-+-+
1403| | | | | | |Q| |
1404+-+-+-+-+-+-+-+-+
1405| | | |Q| | | | |
1406+-+-+-+-+-+-+-+-+
1407| |Q| | | | | | |
1408+-+-+-+-+-+-+-+-+
1409| | | | |Q| | | |
1410+-+-+-+-+-+-+-+-+
1411
Guido van Rossum7131f842007-02-09 20:13:25 +00001412>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000141392 solutions in all.
unknown31569562001-07-04 22:11:22 +00001414
1415And run a Knight's Tour on a 10x10 board. Note that there are about
141620,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1417
Tim Peters9a8c8e22001-07-13 09:12:12 +00001418>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001419>>> LIMIT = 2
1420>>> count = 0
1421>>> for x in k.solve():
1422... count += 1
1423... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001424... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001425... k.printsolution(x)
1426... else:
1427... break
1428Solution 1
1429+---+---+---+---+---+---+---+---+---+---+
1430| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1431+---+---+---+---+---+---+---+---+---+---+
1432| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1433+---+---+---+---+---+---+---+---+---+---+
1434| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1435+---+---+---+---+---+---+---+---+---+---+
1436| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1437+---+---+---+---+---+---+---+---+---+---+
1438| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1439+---+---+---+---+---+---+---+---+---+---+
1440| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1441+---+---+---+---+---+---+---+---+---+---+
1442| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1443+---+---+---+---+---+---+---+---+---+---+
1444| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1445+---+---+---+---+---+---+---+---+---+---+
1446| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1447+---+---+---+---+---+---+---+---+---+---+
1448| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1449+---+---+---+---+---+---+---+---+---+---+
1450Solution 2
1451+---+---+---+---+---+---+---+---+---+---+
1452| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1453+---+---+---+---+---+---+---+---+---+---+
1454| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1455+---+---+---+---+---+---+---+---+---+---+
1456| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1457+---+---+---+---+---+---+---+---+---+---+
1458| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1459+---+---+---+---+---+---+---+---+---+---+
1460| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1461+---+---+---+---+---+---+---+---+---+---+
1462| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1463+---+---+---+---+---+---+---+---+---+---+
1464| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1465+---+---+---+---+---+---+---+---+---+---+
1466| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1467+---+---+---+---+---+---+---+---+---+---+
1468| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1469+---+---+---+---+---+---+---+---+---+---+
1470| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1471+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001472"""
1473
Fred Drake56d12662002-08-09 18:37:10 +00001474weakref_tests = """\
1475Generators are weakly referencable:
1476
1477>>> import weakref
1478>>> def gen():
1479... yield 'foo!'
1480...
1481>>> wr = weakref.ref(gen)
1482>>> wr() is gen
1483True
1484>>> p = weakref.proxy(gen)
1485
1486Generator-iterators are weakly referencable as well:
1487
1488>>> gi = gen()
1489>>> wr = weakref.ref(gi)
1490>>> wr() is gi
1491True
1492>>> p = weakref.proxy(gi)
1493>>> list(p)
1494['foo!']
1495
1496"""
1497
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001498coroutine_tests = """\
1499Sending a value into a started generator:
1500
1501>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001502... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001503... yield 2
1504>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001505>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000015061
1507>>> g.send(42)
150842
15092
1510
1511Sending a value into a new generator produces a TypeError:
1512
1513>>> f().send("foo")
1514Traceback (most recent call last):
1515...
1516TypeError: can't send non-None value to a just-started generator
1517
1518
1519Yield by itself yields None:
1520
1521>>> def f(): yield
1522>>> list(f())
1523[None]
1524
1525
1526
1527An obscene abuse of a yield expression within a generator expression:
1528
1529>>> list((yield 21) for i in range(4))
1530[21, None, 21, None, 21, None, 21, None]
1531
1532And a more sane, but still weird usage:
1533
1534>>> def f(): list(i for i in [(yield 26)])
1535>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001536<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001537
1538
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001539A yield expression with augmented assignment.
1540
1541>>> def coroutine(seq):
1542... count = 0
1543... while count < 200:
1544... count += yield
1545... seq.append(count)
1546>>> seq = []
1547>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001548>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001549>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001550[]
1551>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001552>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001553[10]
1554>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001555>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001556[10, 20]
1557>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001558>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001559[10, 20, 30]
1560
1561
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001562Check some syntax errors for yield expressions:
1563
1564>>> f=lambda: (yield 1),(yield 2)
1565Traceback (most recent call last):
1566 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001567SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001568
1569>>> def f(): return lambda x=(yield): 1
1570Traceback (most recent call last):
1571 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001572SyntaxError: 'return' with argument inside generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001573
1574>>> def f(): x = yield = y
1575Traceback (most recent call last):
1576 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001577SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001578
1579>>> def f(): (yield bar) = y
1580Traceback (most recent call last):
1581 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001582SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001583
1584>>> def f(): (yield bar) += y
1585Traceback (most recent call last):
1586 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001587SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001588
1589
1590Now check some throw() conditions:
1591
1592>>> def f():
1593... while True:
1594... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001595... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001596... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001597... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001598>>> import sys
1599>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001600>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001601
1602>>> g.throw(ValueError) # type only
1603caught ValueError ()
1604
1605>>> g.throw(ValueError("xyz")) # value only
1606caught ValueError (xyz)
1607
1608>>> g.throw(ValueError, ValueError(1)) # value+matching type
1609caught ValueError (1)
1610
1611>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1612caught ValueError (1)
1613
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001614>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1615caught ValueError (1)
1616
Tim Peterse9fe7e02005-08-07 03:04:58 +00001617>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001618Traceback (most recent call last):
1619 ...
1620TypeError: instance exception may not have a separate value
1621
Tim Peterse9fe7e02005-08-07 03:04:58 +00001622>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001623Traceback (most recent call last):
1624 ...
1625TypeError: throw() third argument must be a traceback object
1626
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001627>>> g.throw("abc")
1628Traceback (most recent call last):
1629 ...
1630TypeError: exceptions must be classes or instances deriving from BaseException, not str
1631
1632>>> g.throw(0)
1633Traceback (most recent call last):
1634 ...
1635TypeError: exceptions must be classes or instances deriving from BaseException, not int
1636
1637>>> g.throw(list)
1638Traceback (most recent call last):
1639 ...
1640TypeError: exceptions must be classes or instances deriving from BaseException, not type
1641
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001642>>> def throw(g,exc):
1643... try:
1644... raise exc
1645... except:
1646... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001647>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001648caught ValueError ()
1649
1650>>> g.send(1)
16511
1652
Tim Peterse9fe7e02005-08-07 03:04:58 +00001653>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001654Traceback (most recent call last):
1655 ...
1656TypeError
1657
Guido van Rossum7131f842007-02-09 20:13:25 +00001658>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001659None
1660
1661>>> g.send(2)
1662Traceback (most recent call last):
1663 ...
1664StopIteration
1665
Tim Peterse9fe7e02005-08-07 03:04:58 +00001666>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001667Traceback (most recent call last):
1668 ...
1669ValueError: 6
1670
Tim Peterse9fe7e02005-08-07 03:04:58 +00001671>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001672Traceback (most recent call last):
1673 ...
1674ValueError: 7
1675
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001676Now let's try closing a generator:
1677
1678>>> def f():
1679... try: yield
1680... except GeneratorExit:
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>>> g.close()
1686exiting
1687>>> g.close() # should be no-op now
1688
1689>>> f().close() # close on just-opened generator should be fine
1690
Tim Peterse9fe7e02005-08-07 03:04:58 +00001691>>> def f(): yield # an even simpler generator
1692>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001693>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001694>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001695>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001696
1697And finalization:
1698
1699>>> def f():
1700... try: yield
1701... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001702... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001703
1704>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001705>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001706>>> del g
1707exiting
1708
1709
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001710GeneratorExit is not caught by except Exception:
1711
1712>>> def f():
1713... try: yield
1714... except Exception:
1715... print('except')
1716... finally:
1717... print('finally')
1718
1719>>> g = f()
1720>>> next(g)
1721>>> del g
1722finally
1723
1724
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001725Now let's try some ill-behaved generators:
1726
1727>>> def f():
1728... try: yield
1729... except GeneratorExit:
1730... yield "foo!"
1731>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001732>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001733>>> g.close()
1734Traceback (most recent call last):
1735 ...
1736RuntimeError: generator ignored GeneratorExit
1737>>> g.close()
1738
1739
1740Our ill-behaved code should be invoked during GC:
1741
Guido van Rossum34d19282007-08-09 01:03:29 +00001742>>> import sys, io
1743>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001744>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001745>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001746>>> del g
1747>>> sys.stderr.getvalue().startswith(
Neal Norwitz2633c692007-02-26 22:22:47 +00001748... "Exception RuntimeError: 'generator ignored GeneratorExit' in "
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001749... )
1750True
1751>>> sys.stderr = old
1752
1753
1754And errors thrown during closing should propagate:
1755
1756>>> def f():
1757... try: yield
1758... except GeneratorExit:
1759... raise TypeError("fie!")
1760>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001761>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001762>>> g.close()
1763Traceback (most recent call last):
1764 ...
1765TypeError: fie!
1766
1767
1768Ensure that various yield expression constructs make their
1769enclosing function a generator:
1770
1771>>> def f(): x += yield
1772>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001773<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001774
1775>>> def f(): x = yield
1776>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001777<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001778
1779>>> def f(): lambda x=(yield): 1
1780>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001781<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001782
1783>>> def f(): x=(i for i in (yield) if (yield))
1784>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001785<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001786
1787>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1788>>> data = [1,2]
1789>>> g = f(data)
1790>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00001791<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001792>>> g.send(None)
1793'a'
1794>>> data
1795[1, 2]
1796>>> g.send(0)
1797'b'
1798>>> data
1799[27, 2]
1800>>> try: g.send(1)
1801... except StopIteration: pass
1802>>> data
1803[27, 27]
1804
1805"""
1806
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001807refleaks_tests = """
1808Prior to adding cycle-GC support to itertools.tee, this code would leak
1809references. We add it to the standard suite so the routine refleak-tests
1810would trigger if it starts being uncleanable again.
1811
1812>>> import itertools
1813>>> def leak():
1814... class gen:
1815... def __iter__(self):
1816... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00001817... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001818... return self.item
1819... g = gen()
1820... head, tail = itertools.tee(g)
1821... g.item = head
1822... return head
1823>>> it = leak()
1824
1825Make sure to also test the involvement of the tee-internal teedataobject,
1826which stores returned items.
1827
Georg Brandla18af4e2007-04-21 15:47:16 +00001828>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001829
1830
1831
1832This test leaked at one point due to generator finalization/destruction.
1833It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1834was removed.
1835
1836>>> def leak():
1837... def gen():
1838... while True:
1839... yield g
1840... g = gen()
1841
1842>>> leak()
1843
1844
1845
1846This test isn't really generator related, but rather exception-in-cleanup
1847related. The coroutine tests (above) just happen to cause an exception in
1848the generator's __del__ (tp_del) method. We can also test for this
1849explicitly, without generators. We do have to redirect stderr to avoid
1850printing warnings and to doublecheck that we actually tested what we wanted
1851to test.
1852
Guido van Rossum34d19282007-08-09 01:03:29 +00001853>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001854>>> old = sys.stderr
1855>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00001856... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001857... class Leaker:
1858... def __del__(self):
1859... raise RuntimeError
1860...
1861... l = Leaker()
1862... del l
1863... err = sys.stderr.getvalue().strip()
1864... err.startswith(
Neal Norwitz2633c692007-02-26 22:22:47 +00001865... "Exception RuntimeError: RuntimeError() in <"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001866... )
1867... err.endswith("> ignored")
1868... len(err.splitlines())
1869... finally:
1870... sys.stderr = old
1871True
1872True
18731
1874
1875
1876
1877These refleak tests should perhaps be in a testfile of their own,
1878test_generators just happened to be the test that drew these out.
1879
1880"""
1881
Tim Petersf6ed0742001-06-27 07:17:57 +00001882__test__ = {"tut": tutorial_tests,
1883 "pep": pep_tests,
1884 "email": email_tests,
1885 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001886 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001887 "conjoin": conjoin_tests,
1888 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001889 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001890 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001891 }
Tim Peters1def3512001-06-23 20:27:04 +00001892
1893# Magic test name that regrtest.py invokes *after* importing this module.
1894# This worms around a bootstrap problem.
1895# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1896# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001897def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001898 from test import support, test_generators
1899 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001900
1901# This part isn't needed for regrtest, but for running the test directly.
1902if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001903 test_main(1)