blob: 91afe477994e83c44680098939601a363e82c31e [file] [log] [blame]
Antoine Pitrou796564c2013-07-30 19:59:21 +02001import gc
2import sys
3import unittest
4import weakref
5
6from test import support
7
8
9class FinalizationTest(unittest.TestCase):
10
11 def test_frame_resurrect(self):
12 # A generator frame can be resurrected by a generator's finalization.
13 def gen():
14 nonlocal frame
15 try:
16 yield
17 finally:
18 frame = sys._getframe()
19
20 g = gen()
21 wr = weakref.ref(g)
22 next(g)
23 del g
24 support.gc_collect()
25 self.assertIs(wr(), None)
26 self.assertTrue(frame)
27 del frame
28 support.gc_collect()
29
30 def test_refcycle(self):
31 # A generator caught in a refcycle gets finalized anyway.
32 old_garbage = gc.garbage[:]
33 finalized = False
34 def gen():
35 nonlocal finalized
36 try:
37 g = yield
38 yield 1
39 finally:
40 finalized = True
41
42 g = gen()
43 next(g)
44 g.send(g)
45 self.assertGreater(sys.getrefcount(g), 2)
46 self.assertFalse(finalized)
47 del g
48 support.gc_collect()
49 self.assertTrue(finalized)
50 self.assertEqual(gc.garbage, old_garbage)
51
52
Tim Peters6ba5f792001-06-23 20:45:43 +000053tutorial_tests = """
Tim Peters1def3512001-06-23 20:27:04 +000054Let's try a simple generator:
55
56 >>> def f():
57 ... yield 1
58 ... yield 2
59
Tim Petersb9e9ff12001-06-24 03:44:52 +000060 >>> for i in f():
Guido van Rossum7131f842007-02-09 20:13:25 +000061 ... print(i)
Tim Petersb9e9ff12001-06-24 03:44:52 +000062 1
63 2
Tim Peters1def3512001-06-23 20:27:04 +000064 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +000065 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000066 1
Georg Brandla18af4e2007-04-21 15:47:16 +000067 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000068 2
Tim Petersea2e97a2001-06-24 07:10:02 +000069
Tim Peters2106ef02001-06-25 01:30:12 +000070"Falling off the end" stops the generator:
Tim Petersea2e97a2001-06-24 07:10:02 +000071
Georg Brandla18af4e2007-04-21 15:47:16 +000072 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000073 Traceback (most recent call last):
74 File "<stdin>", line 1, in ?
75 File "<stdin>", line 2, in g
76 StopIteration
77
Tim Petersea2e97a2001-06-24 07:10:02 +000078"return" also stops the generator:
Tim Peters1def3512001-06-23 20:27:04 +000079
80 >>> def f():
81 ... yield 1
82 ... return
83 ... yield 2 # never reached
84 ...
85 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +000086 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000087 1
Georg Brandla18af4e2007-04-21 15:47:16 +000088 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +000089 Traceback (most recent call last):
90 File "<stdin>", line 1, in ?
91 File "<stdin>", line 3, in f
92 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +000093 >>> next(g) # once stopped, can't be resumed
Tim Peters1def3512001-06-23 20:27:04 +000094 Traceback (most recent call last):
95 File "<stdin>", line 1, in ?
96 StopIteration
97
98"raise StopIteration" stops the generator too:
99
100 >>> def f():
101 ... yield 1
Tim Peters34463652001-07-12 22:43:41 +0000102 ... raise StopIteration
Tim Peters1def3512001-06-23 20:27:04 +0000103 ... yield 2 # never reached
104 ...
105 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000106 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000107 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000108 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000109 Traceback (most recent call last):
110 File "<stdin>", line 1, in ?
111 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +0000112 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000113 Traceback (most recent call last):
114 File "<stdin>", line 1, in ?
115 StopIteration
116
117However, they are not exactly equivalent:
118
119 >>> def g1():
120 ... try:
121 ... return
122 ... except:
123 ... yield 1
124 ...
125 >>> list(g1())
126 []
127
128 >>> def g2():
129 ... try:
130 ... raise StopIteration
131 ... except:
132 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000133 >>> print(list(g2()))
Tim Peters1def3512001-06-23 20:27:04 +0000134 [42]
135
136This may be surprising at first:
137
138 >>> def g3():
139 ... try:
140 ... return
141 ... finally:
142 ... yield 1
143 ...
144 >>> list(g3())
145 [1]
146
147Let's create an alternate range() function implemented as a generator:
148
149 >>> def yrange(n):
150 ... for i in range(n):
151 ... yield i
152 ...
153 >>> list(yrange(5))
154 [0, 1, 2, 3, 4]
155
156Generators always return to the most recent caller:
157
158 >>> def creator():
159 ... r = yrange(5)
Georg Brandla18af4e2007-04-21 15:47:16 +0000160 ... print("creator", next(r))
Tim Peters1def3512001-06-23 20:27:04 +0000161 ... return r
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000162 ...
Tim Peters1def3512001-06-23 20:27:04 +0000163 >>> def caller():
164 ... r = creator()
165 ... for i in r:
Guido van Rossum7131f842007-02-09 20:13:25 +0000166 ... print("caller", i)
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000167 ...
Tim Peters1def3512001-06-23 20:27:04 +0000168 >>> caller()
169 creator 0
170 caller 1
171 caller 2
172 caller 3
173 caller 4
174
175Generators can call other generators:
176
177 >>> def zrange(n):
178 ... for i in yrange(n):
179 ... yield i
180 ...
181 >>> list(zrange(5))
182 [0, 1, 2, 3, 4]
183
184"""
185
Tim Peters6ba5f792001-06-23 20:45:43 +0000186# The examples from PEP 255.
187
188pep_tests = """
189
Tim Peterse5614632001-08-15 04:41:19 +0000190Specification: Yield
191
192 Restriction: A generator cannot be resumed while it is actively
193 running:
194
195 >>> def g():
Georg Brandla18af4e2007-04-21 15:47:16 +0000196 ... i = next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000197 ... yield i
198 >>> me = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000199 >>> next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000200 Traceback (most recent call last):
201 ...
202 File "<string>", line 2, in g
203 ValueError: generator already executing
204
Tim Peters6ba5f792001-06-23 20:45:43 +0000205Specification: Return
206
207 Note that return isn't always equivalent to raising StopIteration: the
208 difference lies in how enclosing try/except constructs are treated.
209 For example,
210
211 >>> def f1():
212 ... try:
213 ... return
214 ... except:
215 ... yield 1
Guido van Rossum7131f842007-02-09 20:13:25 +0000216 >>> print(list(f1()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000217 []
218
219 because, as in any function, return simply exits, but
220
221 >>> def f2():
222 ... try:
223 ... raise StopIteration
224 ... except:
225 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000226 >>> print(list(f2()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000227 [42]
228
229 because StopIteration is captured by a bare "except", as is any
230 exception.
231
232Specification: Generators and Exception Propagation
233
234 >>> def f():
Tim Peters3caca232001-12-06 06:23:26 +0000235 ... return 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000236 >>> def g():
237 ... yield f() # the zero division exception propagates
238 ... yield 42 # and we'll never get here
239 >>> k = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000240 >>> next(k)
Tim Peters6ba5f792001-06-23 20:45:43 +0000241 Traceback (most recent call last):
242 File "<stdin>", line 1, in ?
243 File "<stdin>", line 2, in g
244 File "<stdin>", line 2, in f
245 ZeroDivisionError: integer division or modulo by zero
Georg Brandla18af4e2007-04-21 15:47:16 +0000246 >>> next(k) # and the generator cannot be resumed
Tim Peters6ba5f792001-06-23 20:45:43 +0000247 Traceback (most recent call last):
248 File "<stdin>", line 1, in ?
249 StopIteration
250 >>>
251
252Specification: Try/Except/Finally
253
254 >>> def f():
255 ... try:
256 ... yield 1
257 ... try:
258 ... yield 2
Tim Peters3caca232001-12-06 06:23:26 +0000259 ... 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000260 ... yield 3 # never get here
261 ... except ZeroDivisionError:
262 ... yield 4
263 ... yield 5
264 ... raise
265 ... except:
266 ... yield 6
267 ... yield 7 # the "raise" above stops this
268 ... except:
269 ... yield 8
270 ... yield 9
271 ... try:
272 ... x = 12
273 ... finally:
274 ... yield 10
275 ... yield 11
Guido van Rossum7131f842007-02-09 20:13:25 +0000276 >>> print(list(f()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000277 [1, 2, 4, 5, 8, 9, 10, 11]
278 >>>
279
Tim Peters6ba5f792001-06-23 20:45:43 +0000280Guido's binary tree example.
281
282 >>> # A binary tree class.
283 >>> class Tree:
284 ...
285 ... def __init__(self, label, left=None, right=None):
286 ... self.label = label
287 ... self.left = left
288 ... self.right = right
289 ...
290 ... def __repr__(self, level=0, indent=" "):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000291 ... s = level*indent + repr(self.label)
Tim Peters6ba5f792001-06-23 20:45:43 +0000292 ... if self.left:
293 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
294 ... if self.right:
295 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
296 ... return s
297 ...
298 ... def __iter__(self):
299 ... return inorder(self)
300
301 >>> # Create a Tree from a list.
302 >>> def tree(list):
303 ... n = len(list)
304 ... if n == 0:
305 ... return []
Tim Peters3caca232001-12-06 06:23:26 +0000306 ... i = n // 2
Tim Peters6ba5f792001-06-23 20:45:43 +0000307 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
308
309 >>> # Show it off: create a tree.
310 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
311
Tim Petersd674e172002-03-10 07:59:13 +0000312 >>> # A recursive generator that generates Tree labels in in-order.
Tim Peters6ba5f792001-06-23 20:45:43 +0000313 >>> def inorder(t):
314 ... if t:
315 ... for x in inorder(t.left):
316 ... yield x
317 ... yield t.label
318 ... for x in inorder(t.right):
319 ... yield x
320
321 >>> # Show it off: create a tree.
Edward Loper103d26e2004-08-09 02:03:30 +0000322 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
323 >>> # Print the nodes of the tree in in-order.
324 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000325 ... print(' '+x, end='')
326 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 +0000327
328 >>> # A non-recursive generator.
329 >>> def inorder(node):
330 ... stack = []
331 ... while node:
332 ... while node.left:
333 ... stack.append(node)
334 ... node = node.left
335 ... yield node.label
336 ... while not node.right:
337 ... try:
338 ... node = stack.pop()
339 ... except IndexError:
340 ... return
341 ... yield node.label
342 ... node = node.right
343
344 >>> # Exercise the non-recursive generator.
345 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000346 ... print(' '+x, end='')
347 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 +0000348
349"""
350
Tim Petersb2bc6a92001-06-24 10:14:27 +0000351# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000352
353email_tests = """
354
355The difference between yielding None and returning it.
356
357>>> def g():
358... for i in range(3):
359... yield None
360... yield None
361... return
362>>> list(g())
363[None, None, None, None]
364
365Ensure that explicitly raising StopIteration acts like any other exception
366in try/except, not like a return.
367
368>>> def g():
369... yield 1
370... try:
371... raise StopIteration
372... except:
373... yield 2
374... yield 3
375>>> list(g())
376[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000377
Tim Petersb2bc6a92001-06-24 10:14:27 +0000378Next one was posted to c.l.py.
379
380>>> def gcomb(x, k):
381... "Generate all combinations of k elements from list x."
382...
383... if k > len(x):
384... return
385... if k == 0:
386... yield []
387... else:
388... first, rest = x[0], x[1:]
389... # A combination does or doesn't contain first.
390... # If it does, the remainder is a k-1 comb of rest.
391... for c in gcomb(rest, k-1):
392... c.insert(0, first)
393... yield c
394... # If it doesn't contain first, it's a k comb of rest.
395... for c in gcomb(rest, k):
396... yield c
397
Guido van Rossum805365e2007-05-07 22:24:25 +0000398>>> seq = list(range(1, 5))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000399>>> for k in range(len(seq) + 2):
Guido van Rossum7131f842007-02-09 20:13:25 +0000400... print("%d-combs of %s:" % (k, seq))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000401... for c in gcomb(seq, k):
Guido van Rossum7131f842007-02-09 20:13:25 +0000402... print(" ", c)
Tim Petersb2bc6a92001-06-24 10:14:27 +00004030-combs of [1, 2, 3, 4]:
404 []
4051-combs of [1, 2, 3, 4]:
406 [1]
407 [2]
408 [3]
409 [4]
4102-combs of [1, 2, 3, 4]:
411 [1, 2]
412 [1, 3]
413 [1, 4]
414 [2, 3]
415 [2, 4]
416 [3, 4]
4173-combs of [1, 2, 3, 4]:
418 [1, 2, 3]
419 [1, 2, 4]
420 [1, 3, 4]
421 [2, 3, 4]
4224-combs of [1, 2, 3, 4]:
423 [1, 2, 3, 4]
4245-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000425
Tim Peterse77f2e22001-06-26 22:24:51 +0000426From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000427
428>>> def g():
429... yield 1
430...
431>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000432<class 'function'>
Tim Peters3e7b1a02001-06-25 19:46:25 +0000433>>> i = g()
434>>> type(i)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000435<class 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000436>>> [s for s in dir(i) if not s.startswith('_')]
Christian Heimesaf98da12008-01-27 15:18:18 +0000437['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw']
Serhiy Storchaka9a11f172013-01-31 16:11:04 +0200438>>> from test.support import HAVE_DOCSTRINGS
Larry Hastings581ee362014-01-28 05:00:08 -0800439>>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).')
440Implement next(self).
Tim Peters3e7b1a02001-06-25 19:46:25 +0000441>>> iter(i) is i
Guido van Rossum77f6a652002-04-03 22:41:51 +0000442True
Tim Peters3e7b1a02001-06-25 19:46:25 +0000443>>> import types
444>>> isinstance(i, types.GeneratorType)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000445True
Tim Peterse77f2e22001-06-26 22:24:51 +0000446
447And more, added later.
448
449>>> i.gi_running
4500
451>>> type(i.gi_frame)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000452<class 'frame'>
Tim Peterse77f2e22001-06-26 22:24:51 +0000453>>> i.gi_running = 42
454Traceback (most recent call last):
455 ...
Collin Winter42dae6a2007-03-28 21:44:53 +0000456AttributeError: readonly attribute
Tim Peterse77f2e22001-06-26 22:24:51 +0000457>>> def g():
458... yield me.gi_running
459>>> me = g()
460>>> me.gi_running
4610
Georg Brandla18af4e2007-04-21 15:47:16 +0000462>>> next(me)
Tim Peterse77f2e22001-06-26 22:24:51 +00004631
464>>> me.gi_running
4650
Tim Peters35302662001-07-02 01:38:33 +0000466
467A clever union-find implementation from c.l.py, due to David Eppstein.
468Sent: Friday, June 29, 2001 12:16 PM
469To: python-list@python.org
470Subject: Re: PEP 255: Simple Generators
471
472>>> class disjointSet:
473... def __init__(self, name):
474... self.name = name
475... self.parent = None
476... self.generator = self.generate()
477...
478... def generate(self):
479... while not self.parent:
480... yield self
481... for x in self.parent.generator:
482... yield x
483...
484... def find(self):
Georg Brandla18af4e2007-04-21 15:47:16 +0000485... return next(self.generator)
Tim Peters35302662001-07-02 01:38:33 +0000486...
487... def union(self, parent):
488... if self.parent:
489... raise ValueError("Sorry, I'm not a root!")
490... self.parent = parent
491...
492... def __str__(self):
493... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000494
495>>> names = "ABCDEFGHIJKLM"
496>>> sets = [disjointSet(name) for name in names]
497>>> roots = sets[:]
498
499>>> import random
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000500>>> gen = random.Random(42)
Tim Peters35302662001-07-02 01:38:33 +0000501>>> while 1:
502... for s in sets:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000503... print(" %s->%s" % (s, s.find()), end='')
Guido van Rossum7131f842007-02-09 20:13:25 +0000504... print()
Tim Peters35302662001-07-02 01:38:33 +0000505... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000506... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000507... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000508... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000509... s1.union(s2)
Guido van Rossum7131f842007-02-09 20:13:25 +0000510... print("merged", s1, "into", s2)
Tim Peters35302662001-07-02 01:38:33 +0000511... else:
512... break
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000513 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 +0000514merged K into B
515 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 +0000516merged A into F
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000517 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
518merged E into F
519 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
520merged D into C
521 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 +0000522merged M into C
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000523 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
524merged J into B
525 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
526merged B into C
527 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
528merged F into G
529 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
530merged L into C
531 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
532merged G into I
533 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
534merged I into H
535 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
536merged C into H
537 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 +0000538
Tim Peters6ba5f792001-06-23 20:45:43 +0000539"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000540# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000541
Tim Peters0f9da0a2001-06-23 21:01:47 +0000542# Fun tests (for sufficiently warped notions of "fun").
543
544fun_tests = """
545
546Build up to a recursive Sieve of Eratosthenes generator.
547
548>>> def firstn(g, n):
Georg Brandla18af4e2007-04-21 15:47:16 +0000549... return [next(g) for i in range(n)]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000550
551>>> def intsfrom(i):
552... while 1:
553... yield i
554... i += 1
555
556>>> firstn(intsfrom(5), 7)
557[5, 6, 7, 8, 9, 10, 11]
558
559>>> def exclude_multiples(n, ints):
560... for i in ints:
561... if i % n:
562... yield i
563
564>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
565[1, 2, 4, 5, 7, 8]
566
567>>> def sieve(ints):
Georg Brandla18af4e2007-04-21 15:47:16 +0000568... prime = next(ints)
Tim Peters0f9da0a2001-06-23 21:01:47 +0000569... yield prime
570... not_divisible_by_prime = exclude_multiples(prime, ints)
571... for p in sieve(not_divisible_by_prime):
572... yield p
573
574>>> primes = sieve(intsfrom(2))
575>>> firstn(primes, 20)
576[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 +0000577
Tim Petersf6ed0742001-06-27 07:17:57 +0000578
Tim Petersb9e9ff12001-06-24 03:44:52 +0000579Another famous problem: generate all integers of the form
580 2**i * 3**j * 5**k
581in increasing order, where i,j,k >= 0. Trickier than it may look at first!
582Try writing it without generators, and correctly, and without generating
5833 internal results for each result output.
584
585>>> def times(n, g):
586... for i in g:
587... yield n * i
588>>> firstn(times(10, intsfrom(1)), 10)
589[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
590
591>>> def merge(g, h):
Georg Brandla18af4e2007-04-21 15:47:16 +0000592... ng = next(g)
593... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000594... while 1:
595... if ng < nh:
596... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000597... ng = next(g)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000598... elif ng > nh:
599... yield nh
Georg Brandla18af4e2007-04-21 15:47:16 +0000600... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000601... else:
602... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000603... ng = next(g)
604... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000605
Tim Petersf6ed0742001-06-27 07:17:57 +0000606The following works, but is doing a whale of a lot of redundant work --
607it's not clear how to get the internal uses of m235 to share a single
608generator. Note that me_times2 (etc) each need to see every element in the
609result sequence. So this is an example where lazy lists are more natural
610(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000611
612>>> def m235():
613... yield 1
614... me_times2 = times(2, m235())
615... me_times3 = times(3, m235())
616... me_times5 = times(5, m235())
617... for i in merge(merge(me_times2,
618... me_times3),
619... me_times5):
620... yield i
621
Tim Petersf6ed0742001-06-27 07:17:57 +0000622Don't print "too many" of these -- the implementation above is extremely
623inefficient: each call of m235() leads to 3 recursive calls, and in
624turn each of those 3 more, and so on, and so on, until we've descended
625enough levels to satisfy the print stmts. Very odd: when I printed 5
626lines of results below, this managed to screw up Win98's malloc in "the
627usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
628address space, and it *looked* like a very slow leak.
629
Tim Petersb9e9ff12001-06-24 03:44:52 +0000630>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000631>>> for i in range(3):
Guido van Rossum7131f842007-02-09 20:13:25 +0000632... print(firstn(result, 15))
Tim Petersb9e9ff12001-06-24 03:44:52 +0000633[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
634[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
635[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000636
637Heh. Here's one way to get a shared list, complete with an excruciating
638namespace renaming trick. The *pretty* part is that the times() and merge()
639functions can be reused as-is, because they only assume their stream
640arguments are iterable -- a LazyList is the same as a generator to times().
641
642>>> class LazyList:
643... def __init__(self, g):
644... self.sofar = []
Georg Brandla18af4e2007-04-21 15:47:16 +0000645... self.fetch = g.__next__
Tim Petersee309272001-06-24 05:47:06 +0000646...
647... def __getitem__(self, i):
648... sofar, fetch = self.sofar, self.fetch
649... while i >= len(sofar):
650... sofar.append(fetch())
651... return sofar[i]
652
653>>> def m235():
654... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000655... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000656... me_times2 = times(2, m235)
657... me_times3 = times(3, m235)
658... me_times5 = times(5, m235)
659... for i in merge(merge(me_times2,
660... me_times3),
661... me_times5):
662... yield i
663
Tim Petersf6ed0742001-06-27 07:17:57 +0000664Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000665efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000666
Tim Petersee309272001-06-24 05:47:06 +0000667>>> m235 = LazyList(m235())
668>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000669... print([m235[j] for j in range(15*i, 15*(i+1))])
Tim Petersee309272001-06-24 05:47:06 +0000670[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
671[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
672[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
673[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
674[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000675
Tim Petersf6ed0742001-06-27 07:17:57 +0000676Ye olde Fibonacci generator, LazyList style.
677
678>>> def fibgen(a, b):
679...
680... def sum(g, h):
681... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000682... yield next(g) + next(h)
Tim Petersf6ed0742001-06-27 07:17:57 +0000683...
684... def tail(g):
Georg Brandla18af4e2007-04-21 15:47:16 +0000685... next(g) # throw first away
Tim Petersf6ed0742001-06-27 07:17:57 +0000686... for x in g:
687... yield x
688...
689... yield a
690... yield b
691... for s in sum(iter(fib),
692... tail(iter(fib))):
693... yield s
694
695>>> fib = LazyList(fibgen(1, 2))
696>>> firstn(iter(fib), 17)
697[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Georg Brandl52715f62005-08-24 09:02:29 +0000698
699
700Running after your tail with itertools.tee (new in version 2.4)
701
702The algorithms "m235" (Hamming) and Fibonacci presented above are both
703examples of a whole family of FP (functional programming) algorithms
704where a function produces and returns a list while the production algorithm
705suppose the list as already produced by recursively calling itself.
706For these algorithms to work, they must:
707
708- produce at least a first element without presupposing the existence of
709 the rest of the list
710- produce their elements in a lazy manner
711
712To work efficiently, the beginning of the list must not be recomputed over
713and over again. This is ensured in most FP languages as a built-in feature.
714In python, we have to explicitly maintain a list of already computed results
715and abandon genuine recursivity.
716
717This is what had been attempted above with the LazyList class. One problem
718with that class is that it keeps a list of all of the generated results and
719therefore continually grows. This partially defeats the goal of the generator
720concept, viz. produce the results only as needed instead of producing them
721all and thereby wasting memory.
722
723Thanks to itertools.tee, it is now clear "how to get the internal uses of
724m235 to share a single generator".
725
726>>> from itertools import tee
727>>> def m235():
728... def _m235():
729... yield 1
730... for n in merge(times(2, m2),
731... merge(times(3, m3),
732... times(5, m5))):
733... yield n
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000734... m1 = _m235()
735... m2, m3, m5, mRes = tee(m1, 4)
Georg Brandl52715f62005-08-24 09:02:29 +0000736... return mRes
737
738>>> it = m235()
739>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000740... print(firstn(it, 15))
Georg Brandl52715f62005-08-24 09:02:29 +0000741[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
742[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
743[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
744[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
745[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
746
747The "tee" function does just what we want. It internally keeps a generated
748result for as long as it has not been "consumed" from all of the duplicated
749iterators, whereupon it is deleted. You can therefore print the hamming
750sequence during hours without increasing memory usage, or very little.
751
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000752The beauty of it is that recursive running-after-their-tail FP algorithms
Georg Brandl52715f62005-08-24 09:02:29 +0000753are quite straightforwardly expressed with this Python idiom.
754
Georg Brandl52715f62005-08-24 09:02:29 +0000755Ye olde Fibonacci generator, tee style.
756
757>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +0000758...
Georg Brandl52715f62005-08-24 09:02:29 +0000759... def _isum(g, h):
760... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000761... yield next(g) + next(h)
Tim Peters9e34c042005-08-26 15:20:46 +0000762...
Georg Brandl52715f62005-08-24 09:02:29 +0000763... def _fib():
764... yield 1
765... yield 2
Georg Brandla18af4e2007-04-21 15:47:16 +0000766... next(fibTail) # throw first away
Georg Brandl52715f62005-08-24 09:02:29 +0000767... for res in _isum(fibHead, fibTail):
768... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000769...
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000770... realfib = _fib()
771... fibHead, fibTail, fibRes = tee(realfib, 3)
Georg Brandl52715f62005-08-24 09:02:29 +0000772... return fibRes
773
774>>> firstn(fib(), 17)
775[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
776
Tim Peters0f9da0a2001-06-23 21:01:47 +0000777"""
778
Tim Petersb6c3cea2001-06-26 03:36:28 +0000779# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
780# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000781
Tim Petersea2e97a2001-06-24 07:10:02 +0000782syntax_tests = """
783
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000784These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000785
786>>> def f():
787... yield 1
788... return
789
Tim Petersaef8cfa2004-08-27 15:12:49 +0000790>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000791... try:
792... yield 1
793... finally:
794... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000795
Tim Petersaef8cfa2004-08-27 15:12:49 +0000796>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000797... try:
798... try:
Tim Peters3caca232001-12-06 06:23:26 +0000799... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000800... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000801... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000802... except:
803... pass
804... finally:
805... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000806
807>>> def f():
808... try:
809... try:
810... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000811... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000812... except ZeroDivisionError:
813... yield 666
814... except:
815... try:
816... x = 12
817... finally:
818... yield 12
819... except:
820... return
821>>> list(f())
822[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000823
824>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000825... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000826>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000827<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000828
Tim Peters08a898f2001-06-28 01:52:22 +0000829
830>>> def f():
831... if 0:
832... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000833>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000834<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000835
Tim Peters08a898f2001-06-28 01:52:22 +0000836
837>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000838... if 0:
839... yield 1
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 "":
845... yield None
846>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000847<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000848
849>>> def f():
850... return
851... try:
852... if x==4:
853... pass
854... elif 0:
855... try:
Tim Peters3caca232001-12-06 06:23:26 +0000856... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000857... except SyntaxError:
858... pass
859... else:
860... if 0:
861... while 12:
862... x += 1
863... yield 2 # don't blink
864... f(a, b, c, d, e)
865... else:
866... pass
867... except:
868... x = 1
869... return
870>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000871<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000872
873>>> def f():
874... if 0:
875... def g():
876... yield 1
877...
878>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000879<class 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000880
881>>> def f():
882... if 0:
883... class C:
884... def __init__(self):
885... yield 1
886... def f(self):
887... yield 2
888>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000889<class 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000890
891>>> def f():
892... if 0:
893... return
894... if 0:
895... yield 2
896>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000897<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +0000898
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000899This one caused a crash (see SF bug 567538):
900
901>>> def f():
902... for i in range(3):
903... try:
904... continue
905... finally:
906... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000907...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000908>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000909>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009100
Georg Brandla18af4e2007-04-21 15:47:16 +0000911>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009121
Georg Brandla18af4e2007-04-21 15:47:16 +0000913>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009142
Georg Brandla18af4e2007-04-21 15:47:16 +0000915>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000916Traceback (most recent call last):
917StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +0000918
919
920Test the gi_code attribute
921
922>>> def f():
923... yield 5
924...
925>>> g = f()
926>>> g.gi_code is f.__code__
927True
928>>> next(g)
9295
930>>> next(g)
931Traceback (most recent call last):
932StopIteration
933>>> g.gi_code is f.__code__
934True
935
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000936
937Test the __name__ attribute and the repr()
938
939>>> def f():
940... yield 5
941...
942>>> g = f()
943>>> g.__name__
944'f'
945>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000946'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +0000947
948Lambdas shouldn't have their usual return behavior.
949
950>>> x = lambda: (yield 1)
951>>> list(x())
952[1]
953
954>>> x = lambda: ((yield 1), (yield 2))
955>>> list(x())
956[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +0000957"""
958
Tim Petersbe4f0a72001-06-29 02:41:16 +0000959# conjoin is a simple backtracking generator, named in honor of Icon's
960# "conjunction" control structure. Pass a list of no-argument functions
961# that return iterable objects. Easiest to explain by example: assume the
962# function list [x, y, z] is passed. Then conjoin acts like:
963#
964# def g():
965# values = [None] * 3
966# for values[0] in x():
967# for values[1] in y():
968# for values[2] in z():
969# yield values
970#
971# So some 3-lists of values *may* be generated, each time we successfully
972# get into the innermost loop. If an iterator fails (is exhausted) before
973# then, it "backtracks" to get the next value from the nearest enclosing
974# iterator (the one "to the left"), and starts all over again at the next
975# slot (pumps a fresh iterator). Of course this is most useful when the
976# iterators have side-effects, so that which values *can* be generated at
977# each slot depend on the values iterated at previous slots.
978
Benjamin Peterson78565b22009-06-28 19:19:51 +0000979def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000980
981 values = [None] * len(gs)
982
Benjamin Peterson78565b22009-06-28 19:19:51 +0000983 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +0000984 if i >= len(gs):
985 yield values
986 else:
987 for values[i] in gs[i]():
988 for x in gen(i+1):
989 yield x
990
991 for x in gen(0):
992 yield x
993
Tim Petersc468fd22001-06-30 07:29:44 +0000994# That works fine, but recursing a level and checking i against len(gs) for
995# each item produced is inefficient. By doing manual loop unrolling across
996# generator boundaries, it's possible to eliminate most of that overhead.
997# This isn't worth the bother *in general* for generators, but conjoin() is
998# a core building block for some CPU-intensive generator applications.
999
1000def conjoin(gs):
1001
1002 n = len(gs)
1003 values = [None] * n
1004
1005 # Do one loop nest at time recursively, until the # of loop nests
1006 # remaining is divisible by 3.
1007
Benjamin Peterson78565b22009-06-28 19:19:51 +00001008 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001009 if i >= n:
1010 yield values
1011
1012 elif (n-i) % 3:
1013 ip1 = i+1
1014 for values[i] in gs[i]():
1015 for x in gen(ip1):
1016 yield x
1017
1018 else:
1019 for x in _gen3(i):
1020 yield x
1021
1022 # Do three loop nests at a time, recursing only if at least three more
1023 # remain. Don't call directly: this is an internal optimization for
1024 # gen's use.
1025
Benjamin Peterson78565b22009-06-28 19:19:51 +00001026 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001027 assert i < n and (n-i) % 3 == 0
1028 ip1, ip2, ip3 = i+1, i+2, i+3
1029 g, g1, g2 = gs[i : ip3]
1030
1031 if ip3 >= n:
1032 # These are the last three, so we can yield values directly.
1033 for values[i] in g():
1034 for values[ip1] in g1():
1035 for values[ip2] in g2():
1036 yield values
1037
1038 else:
1039 # At least 6 loop nests remain; peel off 3 and recurse for the
1040 # rest.
1041 for values[i] in g():
1042 for values[ip1] in g1():
1043 for values[ip2] in g2():
1044 for x in _gen3(ip3):
1045 yield x
1046
1047 for x in gen(0):
1048 yield x
1049
unknown31569562001-07-04 22:11:22 +00001050# And one more approach: For backtracking apps like the Knight's Tour
1051# solver below, the number of backtracking levels can be enormous (one
1052# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1053# needs 10,000 levels). In such cases Python is likely to run out of
1054# stack space due to recursion. So here's a recursion-free version of
1055# conjoin too.
1056# NOTE WELL: This allows large problems to be solved with only trivial
1057# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001058# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1059# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001060
1061def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1062 n = len(gs)
1063 values = [None] * n
1064 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001065 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001066 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001067 while 1:
1068 # Descend.
1069 try:
1070 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001071 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001072 values[i] = it()
1073 i += 1
1074 except _StopIteration:
1075 pass
unknown31569562001-07-04 22:11:22 +00001076 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001077 assert i == n
1078 yield values
unknown31569562001-07-04 22:11:22 +00001079
Tim Peters9a8c8e22001-07-13 09:12:12 +00001080 # Backtrack until an older iterator can be resumed.
1081 i -= 1
unknown31569562001-07-04 22:11:22 +00001082 while i >= 0:
1083 try:
1084 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001085 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001086 i += 1
1087 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001088 except _StopIteration:
1089 # Continue backtracking.
1090 i -= 1
1091 else:
1092 assert i < 0
1093 break
unknown31569562001-07-04 22:11:22 +00001094
Tim Petersbe4f0a72001-06-29 02:41:16 +00001095# A conjoin-based N-Queens solver.
1096
1097class Queens:
1098 def __init__(self, n):
1099 self.n = n
1100 rangen = range(n)
1101
1102 # Assign a unique int to each column and diagonal.
1103 # columns: n of those, range(n).
1104 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1105 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1106 # based.
1107 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1108 # each, smallest i+j is 0, largest is 2n-2.
1109
1110 # For each square, compute a bit vector of the columns and
1111 # diagonals it covers, and for each row compute a function that
1112 # generates the possiblities for the columns in that row.
1113 self.rowgenerators = []
1114 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001115 rowuses = [(1 << j) | # column ordinal
1116 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1117 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001118 for j in rangen]
1119
1120 def rowgen(rowuses=rowuses):
1121 for j in rangen:
1122 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001123 if uses & self.used == 0:
1124 self.used |= uses
1125 yield j
1126 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001127
1128 self.rowgenerators.append(rowgen)
1129
1130 # Generate solutions.
1131 def solve(self):
1132 self.used = 0
1133 for row2col in conjoin(self.rowgenerators):
1134 yield row2col
1135
1136 def printsolution(self, row2col):
1137 n = self.n
1138 assert n == len(row2col)
1139 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001140 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001141 for i in range(n):
1142 squares = [" " for j in range(n)]
1143 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001144 print("|" + "|".join(squares) + "|")
1145 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001146
unknown31569562001-07-04 22:11:22 +00001147# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1148# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1149# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001150# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001151
1152class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001153 def __init__(self, m, n, hard=0):
1154 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001155
Tim Peters9a8c8e22001-07-13 09:12:12 +00001156 # solve() will set up succs[i] to be a list of square #i's
1157 # successors.
1158 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001159
Tim Peters9a8c8e22001-07-13 09:12:12 +00001160 # Remove i0 from each of its successor's successor lists, i.e.
1161 # successors can't go back to i0 again. Return 0 if we can
1162 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001163
Tim Peters9a8c8e22001-07-13 09:12:12 +00001164 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001165 # If we remove all exits from a free square, we're dead:
1166 # even if we move to it next, we can't leave it again.
1167 # If we create a square with one exit, we must visit it next;
1168 # else somebody else will have to visit it, and since there's
1169 # only one adjacent, there won't be a way to leave it again.
1170 # Finelly, if we create more than one free square with a
1171 # single exit, we can only move to one of them next, leaving
1172 # the other one a dead end.
1173 ne0 = ne1 = 0
1174 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001175 s = succs[i]
1176 s.remove(i0)
1177 e = len(s)
1178 if e == 0:
1179 ne0 += 1
1180 elif e == 1:
1181 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001182 return ne0 == 0 and ne1 < 2
1183
Tim Peters9a8c8e22001-07-13 09:12:12 +00001184 # Put i0 back in each of its successor's successor lists.
1185
1186 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001187 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001188 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001189
1190 # Generate the first move.
1191 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001192 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001193 return
1194
unknown31569562001-07-04 22:11:22 +00001195 # Since we're looking for a cycle, it doesn't matter where we
1196 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001197 corner = self.coords2index(0, 0)
1198 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001199 self.lastij = corner
1200 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001201 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001202
1203 # Generate the second moves.
1204 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001205 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001206 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001207 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001208 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001209 assert len(succs[corner]) == 2
1210 assert self.coords2index(1, 2) in succs[corner]
1211 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001212 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001213 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001214 # to (0, 0). Save its index in self.final so that moves before
1215 # the last know it must be kept free.
1216 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001217 this = self.coords2index(i, j)
1218 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001219 self.final = final
unknown31569562001-07-04 22:11:22 +00001220
Tim Peters9a8c8e22001-07-13 09:12:12 +00001221 remove_from_successors(this)
1222 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001223 self.lastij = this
1224 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001225 succs[final].remove(corner)
1226 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001227
Tim Peters9a8c8e22001-07-13 09:12:12 +00001228 # Generate moves 3 thru m*n-1.
1229 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001230 # If some successor has only one exit, must take it.
1231 # Else favor successors with fewer exits.
1232 candidates = []
1233 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001234 e = len(succs[i])
1235 assert e > 0, "else remove_from_successors() pruning flawed"
1236 if e == 1:
1237 candidates = [(e, i)]
1238 break
1239 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001240 else:
1241 candidates.sort()
1242
1243 for e, i in candidates:
1244 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001245 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001246 self.lastij = i
1247 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001248 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001249
Tim Peters9a8c8e22001-07-13 09:12:12 +00001250 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001251 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001252 # Since the # of backtracking levels is m*n, a poor move early on
1253 # can take eons to undo. Smallest square board for which this
1254 # matters a lot is 52x52.
1255 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001256 # If some successor has only one exit, must take it.
1257 # Else favor successors with fewer exits.
1258 # Break ties via max distance from board centerpoint (favor
1259 # corners and edges whenever possible).
1260 candidates = []
1261 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001262 e = len(succs[i])
1263 assert e > 0, "else remove_from_successors() pruning flawed"
1264 if e == 1:
1265 candidates = [(e, 0, i)]
1266 break
1267 i1, j1 = self.index2coords(i)
1268 d = (i1 - vmid)**2 + (j1 - hmid)**2
1269 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001270 else:
1271 candidates.sort()
1272
1273 for e, d, i in candidates:
1274 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001275 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001276 self.lastij = i
1277 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001278 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001279
1280 # Generate the last move.
1281 def last():
1282 assert self.final in succs[self.lastij]
1283 yield self.final
1284
Tim Peters9a8c8e22001-07-13 09:12:12 +00001285 if m*n < 4:
1286 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001287 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001288 self.squaregenerators = [first, second] + \
1289 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001290 [last]
1291
Tim Peters9a8c8e22001-07-13 09:12:12 +00001292 def coords2index(self, i, j):
1293 assert 0 <= i < self.m
1294 assert 0 <= j < self.n
1295 return i * self.n + j
1296
1297 def index2coords(self, index):
1298 assert 0 <= index < self.m * self.n
1299 return divmod(index, self.n)
1300
1301 def _init_board(self):
1302 succs = self.succs
1303 del succs[:]
1304 m, n = self.m, self.n
1305 c2i = self.coords2index
1306
1307 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1308 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1309 rangen = range(n)
1310 for i in range(m):
1311 for j in rangen:
1312 s = [c2i(i+io, j+jo) for io, jo in offsets
1313 if 0 <= i+io < m and
1314 0 <= j+jo < n]
1315 succs.append(s)
1316
unknown31569562001-07-04 22:11:22 +00001317 # Generate solutions.
1318 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001319 self._init_board()
1320 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001321 yield x
1322
1323 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001324 m, n = self.m, self.n
1325 assert len(x) == m*n
1326 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001327 format = "%" + str(w) + "d"
1328
Tim Peters9a8c8e22001-07-13 09:12:12 +00001329 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001330 k = 1
1331 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001332 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001333 squares[i1][j1] = format % k
1334 k += 1
1335
1336 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001337 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001338 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001339 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001340 print("|" + "|".join(row) + "|")
1341 print(sep)
unknown31569562001-07-04 22:11:22 +00001342
Tim Petersbe4f0a72001-06-29 02:41:16 +00001343conjoin_tests = """
1344
1345Generate the 3-bit binary numbers in order. This illustrates dumbest-
1346possible use of conjoin, just to generate the full cross-product.
1347
unknown31569562001-07-04 22:11:22 +00001348>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001349... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001350[0, 0, 0]
1351[0, 0, 1]
1352[0, 1, 0]
1353[0, 1, 1]
1354[1, 0, 0]
1355[1, 0, 1]
1356[1, 1, 0]
1357[1, 1, 1]
1358
Tim Petersc468fd22001-06-30 07:29:44 +00001359For efficiency in typical backtracking apps, conjoin() yields the same list
1360object each time. So if you want to save away a full account of its
1361generated sequence, you need to copy its results.
1362
1363>>> def gencopy(iterator):
1364... for x in iterator:
1365... yield x[:]
1366
1367>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001368... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001369... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000013700 1 True True
13711 2 True True
13722 4 True True
13733 8 True True
13744 16 True True
13755 32 True True
13766 64 True True
13777 128 True True
13788 256 True True
13799 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001380
Tim Petersbe4f0a72001-06-29 02:41:16 +00001381And run an 8-queens solver.
1382
1383>>> q = Queens(8)
1384>>> LIMIT = 2
1385>>> count = 0
1386>>> for row2col in q.solve():
1387... count += 1
1388... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001389... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001390... q.printsolution(row2col)
1391Solution 1
1392+-+-+-+-+-+-+-+-+
1393|Q| | | | | | | |
1394+-+-+-+-+-+-+-+-+
1395| | | | |Q| | | |
1396+-+-+-+-+-+-+-+-+
1397| | | | | | | |Q|
1398+-+-+-+-+-+-+-+-+
1399| | | | | |Q| | |
1400+-+-+-+-+-+-+-+-+
1401| | |Q| | | | | |
1402+-+-+-+-+-+-+-+-+
1403| | | | | | |Q| |
1404+-+-+-+-+-+-+-+-+
1405| |Q| | | | | | |
1406+-+-+-+-+-+-+-+-+
1407| | | |Q| | | | |
1408+-+-+-+-+-+-+-+-+
1409Solution 2
1410+-+-+-+-+-+-+-+-+
1411|Q| | | | | | | |
1412+-+-+-+-+-+-+-+-+
1413| | | | | |Q| | |
1414+-+-+-+-+-+-+-+-+
1415| | | | | | | |Q|
1416+-+-+-+-+-+-+-+-+
1417| | |Q| | | | | |
1418+-+-+-+-+-+-+-+-+
1419| | | | | | |Q| |
1420+-+-+-+-+-+-+-+-+
1421| | | |Q| | | | |
1422+-+-+-+-+-+-+-+-+
1423| |Q| | | | | | |
1424+-+-+-+-+-+-+-+-+
1425| | | | |Q| | | |
1426+-+-+-+-+-+-+-+-+
1427
Guido van Rossum7131f842007-02-09 20:13:25 +00001428>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000142992 solutions in all.
unknown31569562001-07-04 22:11:22 +00001430
1431And run a Knight's Tour on a 10x10 board. Note that there are about
143220,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1433
Tim Peters9a8c8e22001-07-13 09:12:12 +00001434>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001435>>> LIMIT = 2
1436>>> count = 0
1437>>> for x in k.solve():
1438... count += 1
1439... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001440... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001441... k.printsolution(x)
1442... else:
1443... break
1444Solution 1
1445+---+---+---+---+---+---+---+---+---+---+
1446| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1447+---+---+---+---+---+---+---+---+---+---+
1448| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1449+---+---+---+---+---+---+---+---+---+---+
1450| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1451+---+---+---+---+---+---+---+---+---+---+
1452| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1453+---+---+---+---+---+---+---+---+---+---+
1454| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1455+---+---+---+---+---+---+---+---+---+---+
1456| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1457+---+---+---+---+---+---+---+---+---+---+
1458| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1459+---+---+---+---+---+---+---+---+---+---+
1460| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1461+---+---+---+---+---+---+---+---+---+---+
1462| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1463+---+---+---+---+---+---+---+---+---+---+
1464| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1465+---+---+---+---+---+---+---+---+---+---+
1466Solution 2
1467+---+---+---+---+---+---+---+---+---+---+
1468| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1469+---+---+---+---+---+---+---+---+---+---+
1470| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1471+---+---+---+---+---+---+---+---+---+---+
1472| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1473+---+---+---+---+---+---+---+---+---+---+
1474| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1475+---+---+---+---+---+---+---+---+---+---+
1476| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1477+---+---+---+---+---+---+---+---+---+---+
1478| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1479+---+---+---+---+---+---+---+---+---+---+
1480| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1481+---+---+---+---+---+---+---+---+---+---+
1482| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1483+---+---+---+---+---+---+---+---+---+---+
1484| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1485+---+---+---+---+---+---+---+---+---+---+
1486| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1487+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001488"""
1489
Fred Drake56d12662002-08-09 18:37:10 +00001490weakref_tests = """\
1491Generators are weakly referencable:
1492
1493>>> import weakref
1494>>> def gen():
1495... yield 'foo!'
1496...
1497>>> wr = weakref.ref(gen)
1498>>> wr() is gen
1499True
1500>>> p = weakref.proxy(gen)
1501
1502Generator-iterators are weakly referencable as well:
1503
1504>>> gi = gen()
1505>>> wr = weakref.ref(gi)
1506>>> wr() is gi
1507True
1508>>> p = weakref.proxy(gi)
1509>>> list(p)
1510['foo!']
1511
1512"""
1513
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001514coroutine_tests = """\
1515Sending a value into a started generator:
1516
1517>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001518... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001519... yield 2
1520>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001521>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000015221
1523>>> g.send(42)
152442
15252
1526
1527Sending a value into a new generator produces a TypeError:
1528
1529>>> f().send("foo")
1530Traceback (most recent call last):
1531...
1532TypeError: can't send non-None value to a just-started generator
1533
1534
1535Yield by itself yields None:
1536
1537>>> def f(): yield
1538>>> list(f())
1539[None]
1540
1541
1542
1543An obscene abuse of a yield expression within a generator expression:
1544
1545>>> list((yield 21) for i in range(4))
1546[21, None, 21, None, 21, None, 21, None]
1547
1548And a more sane, but still weird usage:
1549
1550>>> def f(): list(i for i in [(yield 26)])
1551>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001552<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001553
1554
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001555A yield expression with augmented assignment.
1556
1557>>> def coroutine(seq):
1558... count = 0
1559... while count < 200:
1560... count += yield
1561... seq.append(count)
1562>>> seq = []
1563>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001564>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001565>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001566[]
1567>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001568>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001569[10]
1570>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001571>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001572[10, 20]
1573>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001574>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001575[10, 20, 30]
1576
1577
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001578Check some syntax errors for yield expressions:
1579
1580>>> f=lambda: (yield 1),(yield 2)
1581Traceback (most recent call last):
1582 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001583SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001584
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001585>>> def f(): x = yield = y
1586Traceback (most recent call last):
1587 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001588SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001589
1590>>> def f(): (yield bar) = y
1591Traceback (most recent call last):
1592 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001593SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001594
1595>>> def f(): (yield bar) += y
1596Traceback (most recent call last):
1597 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001598SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001599
1600
1601Now check some throw() conditions:
1602
1603>>> def f():
1604... while True:
1605... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001606... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001607... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001608... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001609>>> import sys
1610>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001611>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001612
1613>>> g.throw(ValueError) # type only
1614caught ValueError ()
1615
1616>>> g.throw(ValueError("xyz")) # value only
1617caught ValueError (xyz)
1618
1619>>> g.throw(ValueError, ValueError(1)) # value+matching type
1620caught ValueError (1)
1621
1622>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1623caught ValueError (1)
1624
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001625>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1626caught ValueError (1)
1627
Tim Peterse9fe7e02005-08-07 03:04:58 +00001628>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001629Traceback (most recent call last):
1630 ...
1631TypeError: instance exception may not have a separate value
1632
Tim Peterse9fe7e02005-08-07 03:04:58 +00001633>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001634Traceback (most recent call last):
1635 ...
1636TypeError: throw() third argument must be a traceback object
1637
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001638>>> g.throw("abc")
1639Traceback (most recent call last):
1640 ...
1641TypeError: exceptions must be classes or instances deriving from BaseException, not str
1642
1643>>> g.throw(0)
1644Traceback (most recent call last):
1645 ...
1646TypeError: exceptions must be classes or instances deriving from BaseException, not int
1647
1648>>> g.throw(list)
1649Traceback (most recent call last):
1650 ...
1651TypeError: exceptions must be classes or instances deriving from BaseException, not type
1652
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001653>>> def throw(g,exc):
1654... try:
1655... raise exc
1656... except:
1657... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001658>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001659caught ValueError ()
1660
1661>>> g.send(1)
16621
1663
Tim Peterse9fe7e02005-08-07 03:04:58 +00001664>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001665Traceback (most recent call last):
1666 ...
1667TypeError
1668
Guido van Rossum7131f842007-02-09 20:13:25 +00001669>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001670None
1671
1672>>> g.send(2)
1673Traceback (most recent call last):
1674 ...
1675StopIteration
1676
Tim Peterse9fe7e02005-08-07 03:04:58 +00001677>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001678Traceback (most recent call last):
1679 ...
1680ValueError: 6
1681
Tim Peterse9fe7e02005-08-07 03:04:58 +00001682>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001683Traceback (most recent call last):
1684 ...
1685ValueError: 7
1686
Antoine Pitrou551ba202011-10-18 16:40:50 +02001687Plain "raise" inside a generator should preserve the traceback (#13188).
1688The traceback should have 3 levels:
1689- g.throw()
1690- f()
1691- 1/0
1692
1693>>> def f():
1694... try:
1695... yield
1696... except:
1697... raise
1698>>> g = f()
1699>>> try:
1700... 1/0
1701... except ZeroDivisionError as v:
1702... try:
1703... g.throw(v)
1704... except Exception as w:
1705... tb = w.__traceback__
1706>>> levels = 0
1707>>> while tb:
1708... levels += 1
1709... tb = tb.tb_next
1710>>> levels
17113
1712
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001713Now let's try closing a generator:
1714
1715>>> def f():
1716... try: yield
1717... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00001718... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001719
1720>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001721>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001722>>> g.close()
1723exiting
1724>>> g.close() # should be no-op now
1725
1726>>> f().close() # close on just-opened generator should be fine
1727
Tim Peterse9fe7e02005-08-07 03:04:58 +00001728>>> def f(): yield # an even simpler generator
1729>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001730>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001731>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001732>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001733
1734And finalization:
1735
1736>>> def f():
1737... try: yield
1738... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001739... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001740
1741>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001742>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001743>>> del g
1744exiting
1745
1746
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001747GeneratorExit is not caught by except Exception:
1748
1749>>> def f():
1750... try: yield
1751... except Exception:
1752... print('except')
1753... finally:
1754... print('finally')
1755
1756>>> g = f()
1757>>> next(g)
1758>>> del g
1759finally
1760
1761
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001762Now let's try some ill-behaved generators:
1763
1764>>> def f():
1765... try: yield
1766... except GeneratorExit:
1767... yield "foo!"
1768>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001769>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001770>>> g.close()
1771Traceback (most recent call last):
1772 ...
1773RuntimeError: generator ignored GeneratorExit
1774>>> g.close()
1775
1776
1777Our ill-behaved code should be invoked during GC:
1778
Guido van Rossum34d19282007-08-09 01:03:29 +00001779>>> import sys, io
1780>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001781>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001782>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001783>>> del g
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001784>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001785True
1786>>> sys.stderr = old
1787
1788
1789And errors thrown during closing should propagate:
1790
1791>>> def f():
1792... try: yield
1793... except GeneratorExit:
1794... raise TypeError("fie!")
1795>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001796>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001797>>> g.close()
1798Traceback (most recent call last):
1799 ...
1800TypeError: fie!
1801
1802
1803Ensure that various yield expression constructs make their
1804enclosing function a generator:
1805
1806>>> def f(): x += yield
1807>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001808<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001809
1810>>> def f(): x = yield
1811>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001812<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001813
1814>>> def f(): lambda x=(yield): 1
1815>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001816<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001817
1818>>> def f(): x=(i for i in (yield) if (yield))
1819>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001820<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001821
1822>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1823>>> data = [1,2]
1824>>> g = f(data)
1825>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00001826<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001827>>> g.send(None)
1828'a'
1829>>> data
1830[1, 2]
1831>>> g.send(0)
1832'b'
1833>>> data
1834[27, 2]
1835>>> try: g.send(1)
1836... except StopIteration: pass
1837>>> data
1838[27, 27]
1839
1840"""
1841
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001842refleaks_tests = """
1843Prior to adding cycle-GC support to itertools.tee, this code would leak
1844references. We add it to the standard suite so the routine refleak-tests
1845would trigger if it starts being uncleanable again.
1846
1847>>> import itertools
1848>>> def leak():
1849... class gen:
1850... def __iter__(self):
1851... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00001852... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001853... return self.item
1854... g = gen()
1855... head, tail = itertools.tee(g)
1856... g.item = head
1857... return head
1858>>> it = leak()
1859
1860Make sure to also test the involvement of the tee-internal teedataobject,
1861which stores returned items.
1862
Georg Brandla18af4e2007-04-21 15:47:16 +00001863>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001864
1865
1866
1867This test leaked at one point due to generator finalization/destruction.
1868It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1869was removed.
1870
1871>>> def leak():
1872... def gen():
1873... while True:
1874... yield g
1875... g = gen()
1876
1877>>> leak()
1878
1879
1880
1881This test isn't really generator related, but rather exception-in-cleanup
1882related. The coroutine tests (above) just happen to cause an exception in
1883the generator's __del__ (tp_del) method. We can also test for this
1884explicitly, without generators. We do have to redirect stderr to avoid
1885printing warnings and to doublecheck that we actually tested what we wanted
1886to test.
1887
Guido van Rossum34d19282007-08-09 01:03:29 +00001888>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001889>>> old = sys.stderr
1890>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00001891... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001892... class Leaker:
1893... def __del__(self):
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001894... def invoke(message):
1895... raise RuntimeError(message)
1896... invoke("test")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001897...
1898... l = Leaker()
1899... del l
1900... err = sys.stderr.getvalue().strip()
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001901... "Exception ignored in" in err
1902... "RuntimeError: test" in err
1903... "Traceback" in err
1904... "in invoke" in err
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001905... finally:
1906... sys.stderr = old
1907True
1908True
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001909True
1910True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001911
1912
1913These refleak tests should perhaps be in a testfile of their own,
1914test_generators just happened to be the test that drew these out.
1915
1916"""
1917
Tim Petersf6ed0742001-06-27 07:17:57 +00001918__test__ = {"tut": tutorial_tests,
1919 "pep": pep_tests,
1920 "email": email_tests,
1921 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001922 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001923 "conjoin": conjoin_tests,
1924 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001925 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001926 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001927 }
Tim Peters1def3512001-06-23 20:27:04 +00001928
1929# Magic test name that regrtest.py invokes *after* importing this module.
1930# This worms around a bootstrap problem.
1931# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1932# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001933def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001934 from test import support, test_generators
Antoine Pitrou796564c2013-07-30 19:59:21 +02001935 support.run_unittest(__name__)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001936 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001937
1938# This part isn't needed for regrtest, but for running the test directly.
1939if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001940 test_main(1)