blob: 3882f4cb32231bac520cfb2ba0be78256adb3f5c [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
Victor Stinner40ee3012014-06-16 15:59:28 +020053class GeneratorTest(unittest.TestCase):
54
55 def test_name(self):
56 def func():
57 yield 1
58
59 # check generator names
60 gen = func()
61 self.assertEqual(gen.__name__, "func")
62 self.assertEqual(gen.__qualname__,
63 "GeneratorTest.test_name.<locals>.func")
64
65 # modify generator names
66 gen.__name__ = "name"
67 gen.__qualname__ = "qualname"
68 self.assertEqual(gen.__name__, "name")
69 self.assertEqual(gen.__qualname__, "qualname")
70
71 # generator names must be a string and cannot be deleted
72 self.assertRaises(TypeError, setattr, gen, '__name__', 123)
73 self.assertRaises(TypeError, setattr, gen, '__qualname__', 123)
74 self.assertRaises(TypeError, delattr, gen, '__name__')
75 self.assertRaises(TypeError, delattr, gen, '__qualname__')
76
77 # modify names of the function creating the generator
78 func.__qualname__ = "func_qualname"
79 func.__name__ = "func_name"
80 gen = func()
81 self.assertEqual(gen.__name__, "func_name")
82 self.assertEqual(gen.__qualname__, "func_qualname")
83
84 # unnamed generator
85 gen = (x for x in range(10))
86 self.assertEqual(gen.__name__,
87 "<genexpr>")
88 self.assertEqual(gen.__qualname__,
89 "GeneratorTest.test_name.<locals>.<genexpr>")
90
91
Tim Peters6ba5f792001-06-23 20:45:43 +000092tutorial_tests = """
Tim Peters1def3512001-06-23 20:27:04 +000093Let's try a simple generator:
94
95 >>> def f():
96 ... yield 1
97 ... yield 2
98
Tim Petersb9e9ff12001-06-24 03:44:52 +000099 >>> for i in f():
Guido van Rossum7131f842007-02-09 20:13:25 +0000100 ... print(i)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000101 1
102 2
Tim Peters1def3512001-06-23 20:27:04 +0000103 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000104 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000105 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000106 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000107 2
Tim Petersea2e97a2001-06-24 07:10:02 +0000108
Tim Peters2106ef02001-06-25 01:30:12 +0000109"Falling off the end" stops the generator:
Tim Petersea2e97a2001-06-24 07:10:02 +0000110
Georg Brandla18af4e2007-04-21 15:47:16 +0000111 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000112 Traceback (most recent call last):
113 File "<stdin>", line 1, in ?
114 File "<stdin>", line 2, in g
115 StopIteration
116
Tim Petersea2e97a2001-06-24 07:10:02 +0000117"return" also stops the generator:
Tim Peters1def3512001-06-23 20:27:04 +0000118
119 >>> def f():
120 ... yield 1
121 ... return
122 ... yield 2 # never reached
123 ...
124 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000125 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000126 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000127 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000128 Traceback (most recent call last):
129 File "<stdin>", line 1, in ?
130 File "<stdin>", line 3, in f
131 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +0000132 >>> next(g) # once stopped, can't be resumed
Tim Peters1def3512001-06-23 20:27:04 +0000133 Traceback (most recent call last):
134 File "<stdin>", line 1, in ?
135 StopIteration
136
137"raise StopIteration" stops the generator too:
138
139 >>> def f():
140 ... yield 1
Tim Peters34463652001-07-12 22:43:41 +0000141 ... raise StopIteration
Tim Peters1def3512001-06-23 20:27:04 +0000142 ... yield 2 # never reached
143 ...
144 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000145 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000146 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000147 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000148 Traceback (most recent call last):
149 File "<stdin>", line 1, in ?
150 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +0000151 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000152 Traceback (most recent call last):
153 File "<stdin>", line 1, in ?
154 StopIteration
155
156However, they are not exactly equivalent:
157
158 >>> def g1():
159 ... try:
160 ... return
161 ... except:
162 ... yield 1
163 ...
164 >>> list(g1())
165 []
166
167 >>> def g2():
168 ... try:
169 ... raise StopIteration
170 ... except:
171 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000172 >>> print(list(g2()))
Tim Peters1def3512001-06-23 20:27:04 +0000173 [42]
174
175This may be surprising at first:
176
177 >>> def g3():
178 ... try:
179 ... return
180 ... finally:
181 ... yield 1
182 ...
183 >>> list(g3())
184 [1]
185
186Let's create an alternate range() function implemented as a generator:
187
188 >>> def yrange(n):
189 ... for i in range(n):
190 ... yield i
191 ...
192 >>> list(yrange(5))
193 [0, 1, 2, 3, 4]
194
195Generators always return to the most recent caller:
196
197 >>> def creator():
198 ... r = yrange(5)
Georg Brandla18af4e2007-04-21 15:47:16 +0000199 ... print("creator", next(r))
Tim Peters1def3512001-06-23 20:27:04 +0000200 ... return r
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000201 ...
Tim Peters1def3512001-06-23 20:27:04 +0000202 >>> def caller():
203 ... r = creator()
204 ... for i in r:
Guido van Rossum7131f842007-02-09 20:13:25 +0000205 ... print("caller", i)
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000206 ...
Tim Peters1def3512001-06-23 20:27:04 +0000207 >>> caller()
208 creator 0
209 caller 1
210 caller 2
211 caller 3
212 caller 4
213
214Generators can call other generators:
215
216 >>> def zrange(n):
217 ... for i in yrange(n):
218 ... yield i
219 ...
220 >>> list(zrange(5))
221 [0, 1, 2, 3, 4]
222
223"""
224
Tim Peters6ba5f792001-06-23 20:45:43 +0000225# The examples from PEP 255.
226
227pep_tests = """
228
Tim Peterse5614632001-08-15 04:41:19 +0000229Specification: Yield
230
231 Restriction: A generator cannot be resumed while it is actively
232 running:
233
234 >>> def g():
Georg Brandla18af4e2007-04-21 15:47:16 +0000235 ... i = next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000236 ... yield i
237 >>> me = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000238 >>> next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000239 Traceback (most recent call last):
240 ...
241 File "<string>", line 2, in g
242 ValueError: generator already executing
243
Tim Peters6ba5f792001-06-23 20:45:43 +0000244Specification: Return
245
246 Note that return isn't always equivalent to raising StopIteration: the
247 difference lies in how enclosing try/except constructs are treated.
248 For example,
249
250 >>> def f1():
251 ... try:
252 ... return
253 ... except:
254 ... yield 1
Guido van Rossum7131f842007-02-09 20:13:25 +0000255 >>> print(list(f1()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000256 []
257
258 because, as in any function, return simply exits, but
259
260 >>> def f2():
261 ... try:
262 ... raise StopIteration
263 ... except:
264 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000265 >>> print(list(f2()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000266 [42]
267
268 because StopIteration is captured by a bare "except", as is any
269 exception.
270
271Specification: Generators and Exception Propagation
272
273 >>> def f():
Tim Peters3caca232001-12-06 06:23:26 +0000274 ... return 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000275 >>> def g():
276 ... yield f() # the zero division exception propagates
277 ... yield 42 # and we'll never get here
278 >>> k = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000279 >>> next(k)
Tim Peters6ba5f792001-06-23 20:45:43 +0000280 Traceback (most recent call last):
281 File "<stdin>", line 1, in ?
282 File "<stdin>", line 2, in g
283 File "<stdin>", line 2, in f
284 ZeroDivisionError: integer division or modulo by zero
Georg Brandla18af4e2007-04-21 15:47:16 +0000285 >>> next(k) # and the generator cannot be resumed
Tim Peters6ba5f792001-06-23 20:45:43 +0000286 Traceback (most recent call last):
287 File "<stdin>", line 1, in ?
288 StopIteration
289 >>>
290
291Specification: Try/Except/Finally
292
293 >>> def f():
294 ... try:
295 ... yield 1
296 ... try:
297 ... yield 2
Tim Peters3caca232001-12-06 06:23:26 +0000298 ... 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000299 ... yield 3 # never get here
300 ... except ZeroDivisionError:
301 ... yield 4
302 ... yield 5
303 ... raise
304 ... except:
305 ... yield 6
306 ... yield 7 # the "raise" above stops this
307 ... except:
308 ... yield 8
309 ... yield 9
310 ... try:
311 ... x = 12
312 ... finally:
313 ... yield 10
314 ... yield 11
Guido van Rossum7131f842007-02-09 20:13:25 +0000315 >>> print(list(f()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000316 [1, 2, 4, 5, 8, 9, 10, 11]
317 >>>
318
Tim Peters6ba5f792001-06-23 20:45:43 +0000319Guido's binary tree example.
320
321 >>> # A binary tree class.
322 >>> class Tree:
323 ...
324 ... def __init__(self, label, left=None, right=None):
325 ... self.label = label
326 ... self.left = left
327 ... self.right = right
328 ...
329 ... def __repr__(self, level=0, indent=" "):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000330 ... s = level*indent + repr(self.label)
Tim Peters6ba5f792001-06-23 20:45:43 +0000331 ... if self.left:
332 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
333 ... if self.right:
334 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
335 ... return s
336 ...
337 ... def __iter__(self):
338 ... return inorder(self)
339
340 >>> # Create a Tree from a list.
341 >>> def tree(list):
342 ... n = len(list)
343 ... if n == 0:
344 ... return []
Tim Peters3caca232001-12-06 06:23:26 +0000345 ... i = n // 2
Tim Peters6ba5f792001-06-23 20:45:43 +0000346 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
347
348 >>> # Show it off: create a tree.
349 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
350
Tim Petersd674e172002-03-10 07:59:13 +0000351 >>> # A recursive generator that generates Tree labels in in-order.
Tim Peters6ba5f792001-06-23 20:45:43 +0000352 >>> def inorder(t):
353 ... if t:
354 ... for x in inorder(t.left):
355 ... yield x
356 ... yield t.label
357 ... for x in inorder(t.right):
358 ... yield x
359
360 >>> # Show it off: create a tree.
Edward Loper103d26e2004-08-09 02:03:30 +0000361 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
362 >>> # Print the nodes of the tree in in-order.
363 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000364 ... print(' '+x, end='')
365 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 +0000366
367 >>> # A non-recursive generator.
368 >>> def inorder(node):
369 ... stack = []
370 ... while node:
371 ... while node.left:
372 ... stack.append(node)
373 ... node = node.left
374 ... yield node.label
375 ... while not node.right:
376 ... try:
377 ... node = stack.pop()
378 ... except IndexError:
379 ... return
380 ... yield node.label
381 ... node = node.right
382
383 >>> # Exercise the non-recursive generator.
384 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000385 ... print(' '+x, end='')
386 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 +0000387
388"""
389
Tim Petersb2bc6a92001-06-24 10:14:27 +0000390# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000391
392email_tests = """
393
394The difference between yielding None and returning it.
395
396>>> def g():
397... for i in range(3):
398... yield None
399... yield None
400... return
401>>> list(g())
402[None, None, None, None]
403
404Ensure that explicitly raising StopIteration acts like any other exception
405in try/except, not like a return.
406
407>>> def g():
408... yield 1
409... try:
410... raise StopIteration
411... except:
412... yield 2
413... yield 3
414>>> list(g())
415[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000416
Tim Petersb2bc6a92001-06-24 10:14:27 +0000417Next one was posted to c.l.py.
418
419>>> def gcomb(x, k):
420... "Generate all combinations of k elements from list x."
421...
422... if k > len(x):
423... return
424... if k == 0:
425... yield []
426... else:
427... first, rest = x[0], x[1:]
428... # A combination does or doesn't contain first.
429... # If it does, the remainder is a k-1 comb of rest.
430... for c in gcomb(rest, k-1):
431... c.insert(0, first)
432... yield c
433... # If it doesn't contain first, it's a k comb of rest.
434... for c in gcomb(rest, k):
435... yield c
436
Guido van Rossum805365e2007-05-07 22:24:25 +0000437>>> seq = list(range(1, 5))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000438>>> for k in range(len(seq) + 2):
Guido van Rossum7131f842007-02-09 20:13:25 +0000439... print("%d-combs of %s:" % (k, seq))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000440... for c in gcomb(seq, k):
Guido van Rossum7131f842007-02-09 20:13:25 +0000441... print(" ", c)
Tim Petersb2bc6a92001-06-24 10:14:27 +00004420-combs of [1, 2, 3, 4]:
443 []
4441-combs of [1, 2, 3, 4]:
445 [1]
446 [2]
447 [3]
448 [4]
4492-combs of [1, 2, 3, 4]:
450 [1, 2]
451 [1, 3]
452 [1, 4]
453 [2, 3]
454 [2, 4]
455 [3, 4]
4563-combs of [1, 2, 3, 4]:
457 [1, 2, 3]
458 [1, 2, 4]
459 [1, 3, 4]
460 [2, 3, 4]
4614-combs of [1, 2, 3, 4]:
462 [1, 2, 3, 4]
4635-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000464
Tim Peterse77f2e22001-06-26 22:24:51 +0000465From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000466
467>>> def g():
468... yield 1
469...
470>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000471<class 'function'>
Tim Peters3e7b1a02001-06-25 19:46:25 +0000472>>> i = g()
473>>> type(i)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000474<class 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000475>>> [s for s in dir(i) if not s.startswith('_')]
Christian Heimesaf98da12008-01-27 15:18:18 +0000476['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw']
Serhiy Storchaka9a11f172013-01-31 16:11:04 +0200477>>> from test.support import HAVE_DOCSTRINGS
Larry Hastings581ee362014-01-28 05:00:08 -0800478>>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).')
479Implement next(self).
Tim Peters3e7b1a02001-06-25 19:46:25 +0000480>>> iter(i) is i
Guido van Rossum77f6a652002-04-03 22:41:51 +0000481True
Tim Peters3e7b1a02001-06-25 19:46:25 +0000482>>> import types
483>>> isinstance(i, types.GeneratorType)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000484True
Tim Peterse77f2e22001-06-26 22:24:51 +0000485
486And more, added later.
487
488>>> i.gi_running
4890
490>>> type(i.gi_frame)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000491<class 'frame'>
Tim Peterse77f2e22001-06-26 22:24:51 +0000492>>> i.gi_running = 42
493Traceback (most recent call last):
494 ...
Collin Winter42dae6a2007-03-28 21:44:53 +0000495AttributeError: readonly attribute
Tim Peterse77f2e22001-06-26 22:24:51 +0000496>>> def g():
497... yield me.gi_running
498>>> me = g()
499>>> me.gi_running
5000
Georg Brandla18af4e2007-04-21 15:47:16 +0000501>>> next(me)
Tim Peterse77f2e22001-06-26 22:24:51 +00005021
503>>> me.gi_running
5040
Tim Peters35302662001-07-02 01:38:33 +0000505
506A clever union-find implementation from c.l.py, due to David Eppstein.
507Sent: Friday, June 29, 2001 12:16 PM
508To: python-list@python.org
509Subject: Re: PEP 255: Simple Generators
510
511>>> class disjointSet:
512... def __init__(self, name):
513... self.name = name
514... self.parent = None
515... self.generator = self.generate()
516...
517... def generate(self):
518... while not self.parent:
519... yield self
520... for x in self.parent.generator:
521... yield x
522...
523... def find(self):
Georg Brandla18af4e2007-04-21 15:47:16 +0000524... return next(self.generator)
Tim Peters35302662001-07-02 01:38:33 +0000525...
526... def union(self, parent):
527... if self.parent:
528... raise ValueError("Sorry, I'm not a root!")
529... self.parent = parent
530...
531... def __str__(self):
532... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000533
534>>> names = "ABCDEFGHIJKLM"
535>>> sets = [disjointSet(name) for name in names]
536>>> roots = sets[:]
537
538>>> import random
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000539>>> gen = random.Random(42)
Tim Peters35302662001-07-02 01:38:33 +0000540>>> while 1:
541... for s in sets:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000542... print(" %s->%s" % (s, s.find()), end='')
Guido van Rossum7131f842007-02-09 20:13:25 +0000543... print()
Tim Peters35302662001-07-02 01:38:33 +0000544... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000545... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000546... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000547... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000548... s1.union(s2)
Guido van Rossum7131f842007-02-09 20:13:25 +0000549... print("merged", s1, "into", s2)
Tim Peters35302662001-07-02 01:38:33 +0000550... else:
551... break
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000552 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 +0000553merged K into B
554 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 +0000555merged A into F
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000556 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
557merged E into F
558 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
559merged D into C
560 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 +0000561merged M into C
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000562 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
563merged J into B
564 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
565merged B into C
566 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
567merged F into G
568 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
569merged L into C
570 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
571merged G into I
572 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
573merged I into H
574 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
575merged C into H
576 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 +0000577
Tim Peters6ba5f792001-06-23 20:45:43 +0000578"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000579# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000580
Tim Peters0f9da0a2001-06-23 21:01:47 +0000581# Fun tests (for sufficiently warped notions of "fun").
582
583fun_tests = """
584
585Build up to a recursive Sieve of Eratosthenes generator.
586
587>>> def firstn(g, n):
Georg Brandla18af4e2007-04-21 15:47:16 +0000588... return [next(g) for i in range(n)]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000589
590>>> def intsfrom(i):
591... while 1:
592... yield i
593... i += 1
594
595>>> firstn(intsfrom(5), 7)
596[5, 6, 7, 8, 9, 10, 11]
597
598>>> def exclude_multiples(n, ints):
599... for i in ints:
600... if i % n:
601... yield i
602
603>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
604[1, 2, 4, 5, 7, 8]
605
606>>> def sieve(ints):
Georg Brandla18af4e2007-04-21 15:47:16 +0000607... prime = next(ints)
Tim Peters0f9da0a2001-06-23 21:01:47 +0000608... yield prime
609... not_divisible_by_prime = exclude_multiples(prime, ints)
610... for p in sieve(not_divisible_by_prime):
611... yield p
612
613>>> primes = sieve(intsfrom(2))
614>>> firstn(primes, 20)
615[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 +0000616
Tim Petersf6ed0742001-06-27 07:17:57 +0000617
Tim Petersb9e9ff12001-06-24 03:44:52 +0000618Another famous problem: generate all integers of the form
619 2**i * 3**j * 5**k
620in increasing order, where i,j,k >= 0. Trickier than it may look at first!
621Try writing it without generators, and correctly, and without generating
6223 internal results for each result output.
623
624>>> def times(n, g):
625... for i in g:
626... yield n * i
627>>> firstn(times(10, intsfrom(1)), 10)
628[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
629
630>>> def merge(g, h):
Georg Brandla18af4e2007-04-21 15:47:16 +0000631... ng = next(g)
632... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000633... while 1:
634... if ng < nh:
635... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000636... ng = next(g)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000637... elif ng > nh:
638... yield nh
Georg Brandla18af4e2007-04-21 15:47:16 +0000639... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000640... else:
641... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000642... ng = next(g)
643... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000644
Tim Petersf6ed0742001-06-27 07:17:57 +0000645The following works, but is doing a whale of a lot of redundant work --
646it's not clear how to get the internal uses of m235 to share a single
647generator. Note that me_times2 (etc) each need to see every element in the
648result sequence. So this is an example where lazy lists are more natural
649(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000650
651>>> def m235():
652... yield 1
653... me_times2 = times(2, m235())
654... me_times3 = times(3, m235())
655... me_times5 = times(5, m235())
656... for i in merge(merge(me_times2,
657... me_times3),
658... me_times5):
659... yield i
660
Tim Petersf6ed0742001-06-27 07:17:57 +0000661Don't print "too many" of these -- the implementation above is extremely
662inefficient: each call of m235() leads to 3 recursive calls, and in
663turn each of those 3 more, and so on, and so on, until we've descended
664enough levels to satisfy the print stmts. Very odd: when I printed 5
665lines of results below, this managed to screw up Win98's malloc in "the
666usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
667address space, and it *looked* like a very slow leak.
668
Tim Petersb9e9ff12001-06-24 03:44:52 +0000669>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000670>>> for i in range(3):
Guido van Rossum7131f842007-02-09 20:13:25 +0000671... print(firstn(result, 15))
Tim Petersb9e9ff12001-06-24 03:44:52 +0000672[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
673[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
674[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000675
676Heh. Here's one way to get a shared list, complete with an excruciating
677namespace renaming trick. The *pretty* part is that the times() and merge()
678functions can be reused as-is, because they only assume their stream
679arguments are iterable -- a LazyList is the same as a generator to times().
680
681>>> class LazyList:
682... def __init__(self, g):
683... self.sofar = []
Georg Brandla18af4e2007-04-21 15:47:16 +0000684... self.fetch = g.__next__
Tim Petersee309272001-06-24 05:47:06 +0000685...
686... def __getitem__(self, i):
687... sofar, fetch = self.sofar, self.fetch
688... while i >= len(sofar):
689... sofar.append(fetch())
690... return sofar[i]
691
692>>> def m235():
693... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000694... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000695... me_times2 = times(2, m235)
696... me_times3 = times(3, m235)
697... me_times5 = times(5, m235)
698... for i in merge(merge(me_times2,
699... me_times3),
700... me_times5):
701... yield i
702
Tim Petersf6ed0742001-06-27 07:17:57 +0000703Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000704efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000705
Tim Petersee309272001-06-24 05:47:06 +0000706>>> m235 = LazyList(m235())
707>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000708... print([m235[j] for j in range(15*i, 15*(i+1))])
Tim Petersee309272001-06-24 05:47:06 +0000709[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
710[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
711[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
712[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
713[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000714
Tim Petersf6ed0742001-06-27 07:17:57 +0000715Ye olde Fibonacci generator, LazyList style.
716
717>>> def fibgen(a, b):
718...
719... def sum(g, h):
720... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000721... yield next(g) + next(h)
Tim Petersf6ed0742001-06-27 07:17:57 +0000722...
723... def tail(g):
Georg Brandla18af4e2007-04-21 15:47:16 +0000724... next(g) # throw first away
Tim Petersf6ed0742001-06-27 07:17:57 +0000725... for x in g:
726... yield x
727...
728... yield a
729... yield b
730... for s in sum(iter(fib),
731... tail(iter(fib))):
732... yield s
733
734>>> fib = LazyList(fibgen(1, 2))
735>>> firstn(iter(fib), 17)
736[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Georg Brandl52715f62005-08-24 09:02:29 +0000737
738
739Running after your tail with itertools.tee (new in version 2.4)
740
741The algorithms "m235" (Hamming) and Fibonacci presented above are both
742examples of a whole family of FP (functional programming) algorithms
743where a function produces and returns a list while the production algorithm
744suppose the list as already produced by recursively calling itself.
745For these algorithms to work, they must:
746
747- produce at least a first element without presupposing the existence of
748 the rest of the list
749- produce their elements in a lazy manner
750
751To work efficiently, the beginning of the list must not be recomputed over
752and over again. This is ensured in most FP languages as a built-in feature.
753In python, we have to explicitly maintain a list of already computed results
754and abandon genuine recursivity.
755
756This is what had been attempted above with the LazyList class. One problem
757with that class is that it keeps a list of all of the generated results and
758therefore continually grows. This partially defeats the goal of the generator
759concept, viz. produce the results only as needed instead of producing them
760all and thereby wasting memory.
761
762Thanks to itertools.tee, it is now clear "how to get the internal uses of
763m235 to share a single generator".
764
765>>> from itertools import tee
766>>> def m235():
767... def _m235():
768... yield 1
769... for n in merge(times(2, m2),
770... merge(times(3, m3),
771... times(5, m5))):
772... yield n
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000773... m1 = _m235()
774... m2, m3, m5, mRes = tee(m1, 4)
Georg Brandl52715f62005-08-24 09:02:29 +0000775... return mRes
776
777>>> it = m235()
778>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000779... print(firstn(it, 15))
Georg Brandl52715f62005-08-24 09:02:29 +0000780[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
781[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
782[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
783[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
784[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
785
786The "tee" function does just what we want. It internally keeps a generated
787result for as long as it has not been "consumed" from all of the duplicated
788iterators, whereupon it is deleted. You can therefore print the hamming
789sequence during hours without increasing memory usage, or very little.
790
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000791The beauty of it is that recursive running-after-their-tail FP algorithms
Georg Brandl52715f62005-08-24 09:02:29 +0000792are quite straightforwardly expressed with this Python idiom.
793
Georg Brandl52715f62005-08-24 09:02:29 +0000794Ye olde Fibonacci generator, tee style.
795
796>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +0000797...
Georg Brandl52715f62005-08-24 09:02:29 +0000798... def _isum(g, h):
799... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000800... yield next(g) + next(h)
Tim Peters9e34c042005-08-26 15:20:46 +0000801...
Georg Brandl52715f62005-08-24 09:02:29 +0000802... def _fib():
803... yield 1
804... yield 2
Georg Brandla18af4e2007-04-21 15:47:16 +0000805... next(fibTail) # throw first away
Georg Brandl52715f62005-08-24 09:02:29 +0000806... for res in _isum(fibHead, fibTail):
807... yield res
Tim Peters9e34c042005-08-26 15:20:46 +0000808...
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000809... realfib = _fib()
810... fibHead, fibTail, fibRes = tee(realfib, 3)
Georg Brandl52715f62005-08-24 09:02:29 +0000811... return fibRes
812
813>>> firstn(fib(), 17)
814[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
815
Tim Peters0f9da0a2001-06-23 21:01:47 +0000816"""
817
Tim Petersb6c3cea2001-06-26 03:36:28 +0000818# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
819# hackery.
Tim Petersee309272001-06-24 05:47:06 +0000820
Tim Petersea2e97a2001-06-24 07:10:02 +0000821syntax_tests = """
822
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000823These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +0000824
825>>> def f():
826... yield 1
827... return
828
Tim Petersaef8cfa2004-08-27 15:12:49 +0000829>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000830... try:
831... yield 1
832... finally:
833... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000834
Tim Petersaef8cfa2004-08-27 15:12:49 +0000835>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +0000836... try:
837... try:
Tim Peters3caca232001-12-06 06:23:26 +0000838... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000839... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +0000840... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +0000841... except:
842... pass
843... finally:
844... pass
Tim Petersea2e97a2001-06-24 07:10:02 +0000845
846>>> def f():
847... try:
848... try:
849... yield 12
Tim Peters3caca232001-12-06 06:23:26 +0000850... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +0000851... except ZeroDivisionError:
852... yield 666
853... except:
854... try:
855... x = 12
856... finally:
857... yield 12
858... except:
859... return
860>>> list(f())
861[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +0000862
863>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +0000864... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000865>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000866<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000867
Tim Peters08a898f2001-06-28 01:52:22 +0000868
869>>> def f():
870... if 0:
871... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000872>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000873<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000874
Tim Peters08a898f2001-06-28 01:52:22 +0000875
876>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +0000877... if 0:
878... yield 1
879>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000880<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000881
882>>> def f():
883... if "":
884... yield None
885>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000886<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000887
888>>> def f():
889... return
890... try:
891... if x==4:
892... pass
893... elif 0:
894... try:
Tim Peters3caca232001-12-06 06:23:26 +0000895... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +0000896... except SyntaxError:
897... pass
898... else:
899... if 0:
900... while 12:
901... x += 1
902... yield 2 # don't blink
903... f(a, b, c, d, e)
904... else:
905... pass
906... except:
907... x = 1
908... return
909>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000910<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000911
912>>> def f():
913... if 0:
914... def g():
915... yield 1
916...
917>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000918<class 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +0000919
920>>> def f():
921... if 0:
922... class C:
923... def __init__(self):
924... yield 1
925... def f(self):
926... yield 2
927>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000928<class 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +0000929
930>>> def f():
931... if 0:
932... return
933... if 0:
934... yield 2
935>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +0000936<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +0000937
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000938This one caused a crash (see SF bug 567538):
939
940>>> def f():
941... for i in range(3):
942... try:
943... continue
944... finally:
945... yield i
Tim Petersc411dba2002-07-16 21:35:23 +0000946...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000947>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000948>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009490
Georg Brandla18af4e2007-04-21 15:47:16 +0000950>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009511
Georg Brandla18af4e2007-04-21 15:47:16 +0000952>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00009532
Georg Brandla18af4e2007-04-21 15:47:16 +0000954>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +0000955Traceback (most recent call last):
956StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +0000957
958
959Test the gi_code attribute
960
961>>> def f():
962... yield 5
963...
964>>> g = f()
965>>> g.gi_code is f.__code__
966True
967>>> next(g)
9685
969>>> next(g)
970Traceback (most recent call last):
971StopIteration
972>>> g.gi_code is f.__code__
973True
974
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000975
976Test the __name__ attribute and the repr()
977
978>>> def f():
979... yield 5
980...
981>>> g = f()
982>>> g.__name__
983'f'
984>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000985'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +0000986
987Lambdas shouldn't have their usual return behavior.
988
989>>> x = lambda: (yield 1)
990>>> list(x())
991[1]
992
993>>> x = lambda: ((yield 1), (yield 2))
994>>> list(x())
995[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +0000996"""
997
Tim Petersbe4f0a72001-06-29 02:41:16 +0000998# conjoin is a simple backtracking generator, named in honor of Icon's
999# "conjunction" control structure. Pass a list of no-argument functions
1000# that return iterable objects. Easiest to explain by example: assume the
1001# function list [x, y, z] is passed. Then conjoin acts like:
1002#
1003# def g():
1004# values = [None] * 3
1005# for values[0] in x():
1006# for values[1] in y():
1007# for values[2] in z():
1008# yield values
1009#
1010# So some 3-lists of values *may* be generated, each time we successfully
1011# get into the innermost loop. If an iterator fails (is exhausted) before
1012# then, it "backtracks" to get the next value from the nearest enclosing
1013# iterator (the one "to the left"), and starts all over again at the next
1014# slot (pumps a fresh iterator). Of course this is most useful when the
1015# iterators have side-effects, so that which values *can* be generated at
1016# each slot depend on the values iterated at previous slots.
1017
Benjamin Peterson78565b22009-06-28 19:19:51 +00001018def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001019
1020 values = [None] * len(gs)
1021
Benjamin Peterson78565b22009-06-28 19:19:51 +00001022 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001023 if i >= len(gs):
1024 yield values
1025 else:
1026 for values[i] in gs[i]():
1027 for x in gen(i+1):
1028 yield x
1029
1030 for x in gen(0):
1031 yield x
1032
Tim Petersc468fd22001-06-30 07:29:44 +00001033# That works fine, but recursing a level and checking i against len(gs) for
1034# each item produced is inefficient. By doing manual loop unrolling across
1035# generator boundaries, it's possible to eliminate most of that overhead.
1036# This isn't worth the bother *in general* for generators, but conjoin() is
1037# a core building block for some CPU-intensive generator applications.
1038
1039def conjoin(gs):
1040
1041 n = len(gs)
1042 values = [None] * n
1043
1044 # Do one loop nest at time recursively, until the # of loop nests
1045 # remaining is divisible by 3.
1046
Benjamin Peterson78565b22009-06-28 19:19:51 +00001047 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001048 if i >= n:
1049 yield values
1050
1051 elif (n-i) % 3:
1052 ip1 = i+1
1053 for values[i] in gs[i]():
1054 for x in gen(ip1):
1055 yield x
1056
1057 else:
1058 for x in _gen3(i):
1059 yield x
1060
1061 # Do three loop nests at a time, recursing only if at least three more
1062 # remain. Don't call directly: this is an internal optimization for
1063 # gen's use.
1064
Benjamin Peterson78565b22009-06-28 19:19:51 +00001065 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001066 assert i < n and (n-i) % 3 == 0
1067 ip1, ip2, ip3 = i+1, i+2, i+3
1068 g, g1, g2 = gs[i : ip3]
1069
1070 if ip3 >= n:
1071 # These are the last three, so we can yield values directly.
1072 for values[i] in g():
1073 for values[ip1] in g1():
1074 for values[ip2] in g2():
1075 yield values
1076
1077 else:
1078 # At least 6 loop nests remain; peel off 3 and recurse for the
1079 # rest.
1080 for values[i] in g():
1081 for values[ip1] in g1():
1082 for values[ip2] in g2():
1083 for x in _gen3(ip3):
1084 yield x
1085
1086 for x in gen(0):
1087 yield x
1088
unknown31569562001-07-04 22:11:22 +00001089# And one more approach: For backtracking apps like the Knight's Tour
1090# solver below, the number of backtracking levels can be enormous (one
1091# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1092# needs 10,000 levels). In such cases Python is likely to run out of
1093# stack space due to recursion. So here's a recursion-free version of
1094# conjoin too.
1095# NOTE WELL: This allows large problems to be solved with only trivial
1096# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001097# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1098# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001099
1100def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1101 n = len(gs)
1102 values = [None] * n
1103 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001104 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001105 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001106 while 1:
1107 # Descend.
1108 try:
1109 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001110 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001111 values[i] = it()
1112 i += 1
1113 except _StopIteration:
1114 pass
unknown31569562001-07-04 22:11:22 +00001115 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001116 assert i == n
1117 yield values
unknown31569562001-07-04 22:11:22 +00001118
Tim Peters9a8c8e22001-07-13 09:12:12 +00001119 # Backtrack until an older iterator can be resumed.
1120 i -= 1
unknown31569562001-07-04 22:11:22 +00001121 while i >= 0:
1122 try:
1123 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001124 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001125 i += 1
1126 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001127 except _StopIteration:
1128 # Continue backtracking.
1129 i -= 1
1130 else:
1131 assert i < 0
1132 break
unknown31569562001-07-04 22:11:22 +00001133
Tim Petersbe4f0a72001-06-29 02:41:16 +00001134# A conjoin-based N-Queens solver.
1135
1136class Queens:
1137 def __init__(self, n):
1138 self.n = n
1139 rangen = range(n)
1140
1141 # Assign a unique int to each column and diagonal.
1142 # columns: n of those, range(n).
1143 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1144 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1145 # based.
1146 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1147 # each, smallest i+j is 0, largest is 2n-2.
1148
1149 # For each square, compute a bit vector of the columns and
1150 # diagonals it covers, and for each row compute a function that
1151 # generates the possiblities for the columns in that row.
1152 self.rowgenerators = []
1153 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001154 rowuses = [(1 << j) | # column ordinal
1155 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1156 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001157 for j in rangen]
1158
1159 def rowgen(rowuses=rowuses):
1160 for j in rangen:
1161 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001162 if uses & self.used == 0:
1163 self.used |= uses
1164 yield j
1165 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001166
1167 self.rowgenerators.append(rowgen)
1168
1169 # Generate solutions.
1170 def solve(self):
1171 self.used = 0
1172 for row2col in conjoin(self.rowgenerators):
1173 yield row2col
1174
1175 def printsolution(self, row2col):
1176 n = self.n
1177 assert n == len(row2col)
1178 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001179 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001180 for i in range(n):
1181 squares = [" " for j in range(n)]
1182 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001183 print("|" + "|".join(squares) + "|")
1184 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001185
unknown31569562001-07-04 22:11:22 +00001186# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1187# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1188# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001189# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001190
1191class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001192 def __init__(self, m, n, hard=0):
1193 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001194
Tim Peters9a8c8e22001-07-13 09:12:12 +00001195 # solve() will set up succs[i] to be a list of square #i's
1196 # successors.
1197 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001198
Tim Peters9a8c8e22001-07-13 09:12:12 +00001199 # Remove i0 from each of its successor's successor lists, i.e.
1200 # successors can't go back to i0 again. Return 0 if we can
1201 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001202
Tim Peters9a8c8e22001-07-13 09:12:12 +00001203 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001204 # If we remove all exits from a free square, we're dead:
1205 # even if we move to it next, we can't leave it again.
1206 # If we create a square with one exit, we must visit it next;
1207 # else somebody else will have to visit it, and since there's
1208 # only one adjacent, there won't be a way to leave it again.
1209 # Finelly, if we create more than one free square with a
1210 # single exit, we can only move to one of them next, leaving
1211 # the other one a dead end.
1212 ne0 = ne1 = 0
1213 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001214 s = succs[i]
1215 s.remove(i0)
1216 e = len(s)
1217 if e == 0:
1218 ne0 += 1
1219 elif e == 1:
1220 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001221 return ne0 == 0 and ne1 < 2
1222
Tim Peters9a8c8e22001-07-13 09:12:12 +00001223 # Put i0 back in each of its successor's successor lists.
1224
1225 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001226 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001227 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001228
1229 # Generate the first move.
1230 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001231 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001232 return
1233
unknown31569562001-07-04 22:11:22 +00001234 # Since we're looking for a cycle, it doesn't matter where we
1235 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001236 corner = self.coords2index(0, 0)
1237 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001238 self.lastij = corner
1239 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001240 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001241
1242 # Generate the second moves.
1243 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001244 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001245 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001246 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001247 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001248 assert len(succs[corner]) == 2
1249 assert self.coords2index(1, 2) in succs[corner]
1250 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001251 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001252 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001253 # to (0, 0). Save its index in self.final so that moves before
1254 # the last know it must be kept free.
1255 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001256 this = self.coords2index(i, j)
1257 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001258 self.final = final
unknown31569562001-07-04 22:11:22 +00001259
Tim Peters9a8c8e22001-07-13 09:12:12 +00001260 remove_from_successors(this)
1261 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001262 self.lastij = this
1263 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001264 succs[final].remove(corner)
1265 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001266
Tim Peters9a8c8e22001-07-13 09:12:12 +00001267 # Generate moves 3 thru m*n-1.
1268 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001269 # If some successor has only one exit, must take it.
1270 # Else favor successors with fewer exits.
1271 candidates = []
1272 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001273 e = len(succs[i])
1274 assert e > 0, "else remove_from_successors() pruning flawed"
1275 if e == 1:
1276 candidates = [(e, i)]
1277 break
1278 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001279 else:
1280 candidates.sort()
1281
1282 for e, i in candidates:
1283 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001284 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001285 self.lastij = i
1286 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001287 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001288
Tim Peters9a8c8e22001-07-13 09:12:12 +00001289 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001290 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001291 # Since the # of backtracking levels is m*n, a poor move early on
1292 # can take eons to undo. Smallest square board for which this
1293 # matters a lot is 52x52.
1294 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001295 # If some successor has only one exit, must take it.
1296 # Else favor successors with fewer exits.
1297 # Break ties via max distance from board centerpoint (favor
1298 # corners and edges whenever possible).
1299 candidates = []
1300 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001301 e = len(succs[i])
1302 assert e > 0, "else remove_from_successors() pruning flawed"
1303 if e == 1:
1304 candidates = [(e, 0, i)]
1305 break
1306 i1, j1 = self.index2coords(i)
1307 d = (i1 - vmid)**2 + (j1 - hmid)**2
1308 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001309 else:
1310 candidates.sort()
1311
1312 for e, d, i in candidates:
1313 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001314 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001315 self.lastij = i
1316 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001317 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001318
1319 # Generate the last move.
1320 def last():
1321 assert self.final in succs[self.lastij]
1322 yield self.final
1323
Tim Peters9a8c8e22001-07-13 09:12:12 +00001324 if m*n < 4:
1325 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001326 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001327 self.squaregenerators = [first, second] + \
1328 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001329 [last]
1330
Tim Peters9a8c8e22001-07-13 09:12:12 +00001331 def coords2index(self, i, j):
1332 assert 0 <= i < self.m
1333 assert 0 <= j < self.n
1334 return i * self.n + j
1335
1336 def index2coords(self, index):
1337 assert 0 <= index < self.m * self.n
1338 return divmod(index, self.n)
1339
1340 def _init_board(self):
1341 succs = self.succs
1342 del succs[:]
1343 m, n = self.m, self.n
1344 c2i = self.coords2index
1345
1346 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1347 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1348 rangen = range(n)
1349 for i in range(m):
1350 for j in rangen:
1351 s = [c2i(i+io, j+jo) for io, jo in offsets
1352 if 0 <= i+io < m and
1353 0 <= j+jo < n]
1354 succs.append(s)
1355
unknown31569562001-07-04 22:11:22 +00001356 # Generate solutions.
1357 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001358 self._init_board()
1359 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001360 yield x
1361
1362 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001363 m, n = self.m, self.n
1364 assert len(x) == m*n
1365 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001366 format = "%" + str(w) + "d"
1367
Tim Peters9a8c8e22001-07-13 09:12:12 +00001368 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001369 k = 1
1370 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001371 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001372 squares[i1][j1] = format % k
1373 k += 1
1374
1375 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001376 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001377 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001378 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001379 print("|" + "|".join(row) + "|")
1380 print(sep)
unknown31569562001-07-04 22:11:22 +00001381
Tim Petersbe4f0a72001-06-29 02:41:16 +00001382conjoin_tests = """
1383
1384Generate the 3-bit binary numbers in order. This illustrates dumbest-
1385possible use of conjoin, just to generate the full cross-product.
1386
unknown31569562001-07-04 22:11:22 +00001387>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001388... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001389[0, 0, 0]
1390[0, 0, 1]
1391[0, 1, 0]
1392[0, 1, 1]
1393[1, 0, 0]
1394[1, 0, 1]
1395[1, 1, 0]
1396[1, 1, 1]
1397
Tim Petersc468fd22001-06-30 07:29:44 +00001398For efficiency in typical backtracking apps, conjoin() yields the same list
1399object each time. So if you want to save away a full account of its
1400generated sequence, you need to copy its results.
1401
1402>>> def gencopy(iterator):
1403... for x in iterator:
1404... yield x[:]
1405
1406>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001407... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001408... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000014090 1 True True
14101 2 True True
14112 4 True True
14123 8 True True
14134 16 True True
14145 32 True True
14156 64 True True
14167 128 True True
14178 256 True True
14189 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001419
Tim Petersbe4f0a72001-06-29 02:41:16 +00001420And run an 8-queens solver.
1421
1422>>> q = Queens(8)
1423>>> LIMIT = 2
1424>>> count = 0
1425>>> for row2col in q.solve():
1426... count += 1
1427... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001428... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001429... q.printsolution(row2col)
1430Solution 1
1431+-+-+-+-+-+-+-+-+
1432|Q| | | | | | | |
1433+-+-+-+-+-+-+-+-+
1434| | | | |Q| | | |
1435+-+-+-+-+-+-+-+-+
1436| | | | | | | |Q|
1437+-+-+-+-+-+-+-+-+
1438| | | | | |Q| | |
1439+-+-+-+-+-+-+-+-+
1440| | |Q| | | | | |
1441+-+-+-+-+-+-+-+-+
1442| | | | | | |Q| |
1443+-+-+-+-+-+-+-+-+
1444| |Q| | | | | | |
1445+-+-+-+-+-+-+-+-+
1446| | | |Q| | | | |
1447+-+-+-+-+-+-+-+-+
1448Solution 2
1449+-+-+-+-+-+-+-+-+
1450|Q| | | | | | | |
1451+-+-+-+-+-+-+-+-+
1452| | | | | |Q| | |
1453+-+-+-+-+-+-+-+-+
1454| | | | | | | |Q|
1455+-+-+-+-+-+-+-+-+
1456| | |Q| | | | | |
1457+-+-+-+-+-+-+-+-+
1458| | | | | | |Q| |
1459+-+-+-+-+-+-+-+-+
1460| | | |Q| | | | |
1461+-+-+-+-+-+-+-+-+
1462| |Q| | | | | | |
1463+-+-+-+-+-+-+-+-+
1464| | | | |Q| | | |
1465+-+-+-+-+-+-+-+-+
1466
Guido van Rossum7131f842007-02-09 20:13:25 +00001467>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000146892 solutions in all.
unknown31569562001-07-04 22:11:22 +00001469
1470And run a Knight's Tour on a 10x10 board. Note that there are about
147120,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1472
Tim Peters9a8c8e22001-07-13 09:12:12 +00001473>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001474>>> LIMIT = 2
1475>>> count = 0
1476>>> for x in k.solve():
1477... count += 1
1478... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001479... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001480... k.printsolution(x)
1481... else:
1482... break
1483Solution 1
1484+---+---+---+---+---+---+---+---+---+---+
1485| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1486+---+---+---+---+---+---+---+---+---+---+
1487| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1488+---+---+---+---+---+---+---+---+---+---+
1489| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1490+---+---+---+---+---+---+---+---+---+---+
1491| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1492+---+---+---+---+---+---+---+---+---+---+
1493| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1494+---+---+---+---+---+---+---+---+---+---+
1495| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1496+---+---+---+---+---+---+---+---+---+---+
1497| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1498+---+---+---+---+---+---+---+---+---+---+
1499| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1500+---+---+---+---+---+---+---+---+---+---+
1501| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1502+---+---+---+---+---+---+---+---+---+---+
1503| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1504+---+---+---+---+---+---+---+---+---+---+
1505Solution 2
1506+---+---+---+---+---+---+---+---+---+---+
1507| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1508+---+---+---+---+---+---+---+---+---+---+
1509| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1510+---+---+---+---+---+---+---+---+---+---+
1511| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1512+---+---+---+---+---+---+---+---+---+---+
1513| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1514+---+---+---+---+---+---+---+---+---+---+
1515| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1516+---+---+---+---+---+---+---+---+---+---+
1517| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1518+---+---+---+---+---+---+---+---+---+---+
1519| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1520+---+---+---+---+---+---+---+---+---+---+
1521| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1522+---+---+---+---+---+---+---+---+---+---+
1523| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1524+---+---+---+---+---+---+---+---+---+---+
1525| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1526+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001527"""
1528
Fred Drake56d12662002-08-09 18:37:10 +00001529weakref_tests = """\
1530Generators are weakly referencable:
1531
1532>>> import weakref
1533>>> def gen():
1534... yield 'foo!'
1535...
1536>>> wr = weakref.ref(gen)
1537>>> wr() is gen
1538True
1539>>> p = weakref.proxy(gen)
1540
1541Generator-iterators are weakly referencable as well:
1542
1543>>> gi = gen()
1544>>> wr = weakref.ref(gi)
1545>>> wr() is gi
1546True
1547>>> p = weakref.proxy(gi)
1548>>> list(p)
1549['foo!']
1550
1551"""
1552
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001553coroutine_tests = """\
1554Sending a value into a started generator:
1555
1556>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001557... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001558... yield 2
1559>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001560>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000015611
1562>>> g.send(42)
156342
15642
1565
1566Sending a value into a new generator produces a TypeError:
1567
1568>>> f().send("foo")
1569Traceback (most recent call last):
1570...
1571TypeError: can't send non-None value to a just-started generator
1572
1573
1574Yield by itself yields None:
1575
1576>>> def f(): yield
1577>>> list(f())
1578[None]
1579
1580
1581
1582An obscene abuse of a yield expression within a generator expression:
1583
1584>>> list((yield 21) for i in range(4))
1585[21, None, 21, None, 21, None, 21, None]
1586
1587And a more sane, but still weird usage:
1588
1589>>> def f(): list(i for i in [(yield 26)])
1590>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001591<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001592
1593
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001594A yield expression with augmented assignment.
1595
1596>>> def coroutine(seq):
1597... count = 0
1598... while count < 200:
1599... count += yield
1600... seq.append(count)
1601>>> seq = []
1602>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001603>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001604>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001605[]
1606>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001607>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001608[10]
1609>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001610>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001611[10, 20]
1612>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001613>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001614[10, 20, 30]
1615
1616
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001617Check some syntax errors for yield expressions:
1618
1619>>> f=lambda: (yield 1),(yield 2)
1620Traceback (most recent call last):
1621 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001622SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001623
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001624>>> def f(): x = yield = y
1625Traceback (most recent call last):
1626 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001627SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001628
1629>>> def f(): (yield bar) = y
1630Traceback (most recent call last):
1631 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001632SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001633
1634>>> def f(): (yield bar) += y
1635Traceback (most recent call last):
1636 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001637SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001638
1639
1640Now check some throw() conditions:
1641
1642>>> def f():
1643... while True:
1644... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001645... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001646... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001647... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001648>>> import sys
1649>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001650>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001651
1652>>> g.throw(ValueError) # type only
1653caught ValueError ()
1654
1655>>> g.throw(ValueError("xyz")) # value only
1656caught ValueError (xyz)
1657
1658>>> g.throw(ValueError, ValueError(1)) # value+matching type
1659caught ValueError (1)
1660
1661>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1662caught ValueError (1)
1663
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001664>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1665caught ValueError (1)
1666
Tim Peterse9fe7e02005-08-07 03:04:58 +00001667>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001668Traceback (most recent call last):
1669 ...
1670TypeError: instance exception may not have a separate value
1671
Tim Peterse9fe7e02005-08-07 03:04:58 +00001672>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001673Traceback (most recent call last):
1674 ...
1675TypeError: throw() third argument must be a traceback object
1676
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001677>>> g.throw("abc")
1678Traceback (most recent call last):
1679 ...
1680TypeError: exceptions must be classes or instances deriving from BaseException, not str
1681
1682>>> g.throw(0)
1683Traceback (most recent call last):
1684 ...
1685TypeError: exceptions must be classes or instances deriving from BaseException, not int
1686
1687>>> g.throw(list)
1688Traceback (most recent call last):
1689 ...
1690TypeError: exceptions must be classes or instances deriving from BaseException, not type
1691
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001692>>> def throw(g,exc):
1693... try:
1694... raise exc
1695... except:
1696... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001697>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001698caught ValueError ()
1699
1700>>> g.send(1)
17011
1702
Tim Peterse9fe7e02005-08-07 03:04:58 +00001703>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001704Traceback (most recent call last):
1705 ...
1706TypeError
1707
Guido van Rossum7131f842007-02-09 20:13:25 +00001708>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001709None
1710
1711>>> g.send(2)
1712Traceback (most recent call last):
1713 ...
1714StopIteration
1715
Tim Peterse9fe7e02005-08-07 03:04:58 +00001716>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001717Traceback (most recent call last):
1718 ...
1719ValueError: 6
1720
Tim Peterse9fe7e02005-08-07 03:04:58 +00001721>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001722Traceback (most recent call last):
1723 ...
1724ValueError: 7
1725
Antoine Pitrou551ba202011-10-18 16:40:50 +02001726Plain "raise" inside a generator should preserve the traceback (#13188).
1727The traceback should have 3 levels:
1728- g.throw()
1729- f()
1730- 1/0
1731
1732>>> def f():
1733... try:
1734... yield
1735... except:
1736... raise
1737>>> g = f()
1738>>> try:
1739... 1/0
1740... except ZeroDivisionError as v:
1741... try:
1742... g.throw(v)
1743... except Exception as w:
1744... tb = w.__traceback__
1745>>> levels = 0
1746>>> while tb:
1747... levels += 1
1748... tb = tb.tb_next
1749>>> levels
17503
1751
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001752Now let's try closing a generator:
1753
1754>>> def f():
1755... try: yield
1756... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00001757... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001758
1759>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001760>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001761>>> g.close()
1762exiting
1763>>> g.close() # should be no-op now
1764
1765>>> f().close() # close on just-opened generator should be fine
1766
Tim Peterse9fe7e02005-08-07 03:04:58 +00001767>>> def f(): yield # an even simpler generator
1768>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001769>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001770>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001771>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001772
1773And finalization:
1774
1775>>> def f():
1776... try: yield
1777... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001778... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001779
1780>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001781>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001782>>> del g
1783exiting
1784
1785
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001786GeneratorExit is not caught by except Exception:
1787
1788>>> def f():
1789... try: yield
1790... except Exception:
1791... print('except')
1792... finally:
1793... print('finally')
1794
1795>>> g = f()
1796>>> next(g)
1797>>> del g
1798finally
1799
1800
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001801Now let's try some ill-behaved generators:
1802
1803>>> def f():
1804... try: yield
1805... except GeneratorExit:
1806... yield "foo!"
1807>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001808>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001809>>> g.close()
1810Traceback (most recent call last):
1811 ...
1812RuntimeError: generator ignored GeneratorExit
1813>>> g.close()
1814
1815
1816Our ill-behaved code should be invoked during GC:
1817
Guido van Rossum34d19282007-08-09 01:03:29 +00001818>>> import sys, io
1819>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001820>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001821>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001822>>> del g
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001823>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001824True
1825>>> sys.stderr = old
1826
1827
1828And errors thrown during closing should propagate:
1829
1830>>> def f():
1831... try: yield
1832... except GeneratorExit:
1833... raise TypeError("fie!")
1834>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001835>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001836>>> g.close()
1837Traceback (most recent call last):
1838 ...
1839TypeError: fie!
1840
1841
1842Ensure that various yield expression constructs make their
1843enclosing function a generator:
1844
1845>>> def f(): x += yield
1846>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001847<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001848
1849>>> def f(): x = yield
1850>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001851<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001852
1853>>> def f(): lambda x=(yield): 1
1854>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001855<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001856
1857>>> def f(): x=(i for i in (yield) if (yield))
1858>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001859<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001860
1861>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
1862>>> data = [1,2]
1863>>> g = f(data)
1864>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00001865<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001866>>> g.send(None)
1867'a'
1868>>> data
1869[1, 2]
1870>>> g.send(0)
1871'b'
1872>>> data
1873[27, 2]
1874>>> try: g.send(1)
1875... except StopIteration: pass
1876>>> data
1877[27, 27]
1878
1879"""
1880
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001881refleaks_tests = """
1882Prior to adding cycle-GC support to itertools.tee, this code would leak
1883references. We add it to the standard suite so the routine refleak-tests
1884would trigger if it starts being uncleanable again.
1885
1886>>> import itertools
1887>>> def leak():
1888... class gen:
1889... def __iter__(self):
1890... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00001891... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001892... return self.item
1893... g = gen()
1894... head, tail = itertools.tee(g)
1895... g.item = head
1896... return head
1897>>> it = leak()
1898
1899Make sure to also test the involvement of the tee-internal teedataobject,
1900which stores returned items.
1901
Georg Brandla18af4e2007-04-21 15:47:16 +00001902>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001903
1904
1905
1906This test leaked at one point due to generator finalization/destruction.
1907It was copied from Lib/test/leakers/test_generator_cycle.py before the file
1908was removed.
1909
1910>>> def leak():
1911... def gen():
1912... while True:
1913... yield g
1914... g = gen()
1915
1916>>> leak()
1917
1918
1919
1920This test isn't really generator related, but rather exception-in-cleanup
1921related. The coroutine tests (above) just happen to cause an exception in
1922the generator's __del__ (tp_del) method. We can also test for this
1923explicitly, without generators. We do have to redirect stderr to avoid
1924printing warnings and to doublecheck that we actually tested what we wanted
1925to test.
1926
Guido van Rossum34d19282007-08-09 01:03:29 +00001927>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001928>>> old = sys.stderr
1929>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00001930... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001931... class Leaker:
1932... def __del__(self):
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001933... def invoke(message):
1934... raise RuntimeError(message)
1935... invoke("test")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001936...
1937... l = Leaker()
1938... del l
1939... err = sys.stderr.getvalue().strip()
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001940... "Exception ignored in" in err
1941... "RuntimeError: test" in err
1942... "Traceback" in err
1943... "in invoke" in err
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001944... finally:
1945... sys.stderr = old
1946True
1947True
Andrew Svetlov76bcff22012-11-03 15:56:05 +02001948True
1949True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001950
1951
1952These refleak tests should perhaps be in a testfile of their own,
1953test_generators just happened to be the test that drew these out.
1954
1955"""
1956
Tim Petersf6ed0742001-06-27 07:17:57 +00001957__test__ = {"tut": tutorial_tests,
1958 "pep": pep_tests,
1959 "email": email_tests,
1960 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00001961 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001962 "conjoin": conjoin_tests,
1963 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001964 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001965 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00001966 }
Tim Peters1def3512001-06-23 20:27:04 +00001967
1968# Magic test name that regrtest.py invokes *after* importing this module.
1969# This worms around a bootstrap problem.
1970# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1971# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00001972def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001973 from test import support, test_generators
Antoine Pitrou796564c2013-07-30 19:59:21 +02001974 support.run_unittest(__name__)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001975 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00001976
1977# This part isn't needed for regrtest, but for running the test directly.
1978if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00001979 test_main(1)