blob: 3f82462478d5e1873e3904208a02c8ff45aeb3b5 [file] [log] [blame]
Serhiy Storchakad7a44152015-11-12 11:23:04 +02001import copy
Antoine Pitrou796564c2013-07-30 19:59:21 +02002import gc
Serhiy Storchakad7a44152015-11-12 11:23:04 +02003import pickle
Antoine Pitrou796564c2013-07-30 19:59:21 +02004import sys
5import unittest
Yury Selivanov68333392015-05-22 11:16:47 -04006import warnings
Antoine Pitrou796564c2013-07-30 19:59:21 +02007import weakref
Yury Selivanove13f8f32015-07-03 00:23:30 -04008import inspect
9import types
Antoine Pitrou796564c2013-07-30 19:59:21 +020010
11from test import support
12
13
14class FinalizationTest(unittest.TestCase):
15
16 def test_frame_resurrect(self):
17 # A generator frame can be resurrected by a generator's finalization.
18 def gen():
19 nonlocal frame
20 try:
21 yield
22 finally:
23 frame = sys._getframe()
24
25 g = gen()
26 wr = weakref.ref(g)
27 next(g)
28 del g
29 support.gc_collect()
30 self.assertIs(wr(), None)
31 self.assertTrue(frame)
32 del frame
33 support.gc_collect()
34
35 def test_refcycle(self):
36 # A generator caught in a refcycle gets finalized anyway.
37 old_garbage = gc.garbage[:]
38 finalized = False
39 def gen():
40 nonlocal finalized
41 try:
42 g = yield
43 yield 1
44 finally:
45 finalized = True
46
47 g = gen()
48 next(g)
49 g.send(g)
50 self.assertGreater(sys.getrefcount(g), 2)
51 self.assertFalse(finalized)
52 del g
53 support.gc_collect()
54 self.assertTrue(finalized)
55 self.assertEqual(gc.garbage, old_garbage)
56
Serhiy Storchakac775ad62015-03-11 18:20:35 +020057 def test_lambda_generator(self):
58 # Issue #23192: Test that a lambda returning a generator behaves
59 # like the equivalent function
60 f = lambda: (yield 1)
61 def g(): return (yield 1)
62
63 # test 'yield from'
64 f2 = lambda: (yield from g())
65 def g2(): return (yield from g())
66
67 f3 = lambda: (yield from f())
68 def g3(): return (yield from f())
69
70 for gen_fun in (f, g, f2, g2, f3, g3):
71 gen = gen_fun()
72 self.assertEqual(next(gen), 1)
73 with self.assertRaises(StopIteration) as cm:
74 gen.send(2)
75 self.assertEqual(cm.exception.value, 2)
76
Antoine Pitrou796564c2013-07-30 19:59:21 +020077
Victor Stinner40ee3012014-06-16 15:59:28 +020078class GeneratorTest(unittest.TestCase):
79
80 def test_name(self):
81 def func():
82 yield 1
83
84 # check generator names
85 gen = func()
86 self.assertEqual(gen.__name__, "func")
87 self.assertEqual(gen.__qualname__,
88 "GeneratorTest.test_name.<locals>.func")
89
90 # modify generator names
91 gen.__name__ = "name"
92 gen.__qualname__ = "qualname"
93 self.assertEqual(gen.__name__, "name")
94 self.assertEqual(gen.__qualname__, "qualname")
95
96 # generator names must be a string and cannot be deleted
97 self.assertRaises(TypeError, setattr, gen, '__name__', 123)
98 self.assertRaises(TypeError, setattr, gen, '__qualname__', 123)
99 self.assertRaises(TypeError, delattr, gen, '__name__')
100 self.assertRaises(TypeError, delattr, gen, '__qualname__')
101
102 # modify names of the function creating the generator
103 func.__qualname__ = "func_qualname"
104 func.__name__ = "func_name"
105 gen = func()
106 self.assertEqual(gen.__name__, "func_name")
107 self.assertEqual(gen.__qualname__, "func_qualname")
108
109 # unnamed generator
110 gen = (x for x in range(10))
111 self.assertEqual(gen.__name__,
112 "<genexpr>")
113 self.assertEqual(gen.__qualname__,
114 "GeneratorTest.test_name.<locals>.<genexpr>")
115
Serhiy Storchakad7a44152015-11-12 11:23:04 +0200116 def test_copy(self):
117 def f():
118 yield 1
119 g = f()
120 with self.assertRaises(TypeError):
121 copy.copy(g)
122
123 def test_pickle(self):
124 def f():
125 yield 1
126 g = f()
127 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
128 with self.assertRaises((TypeError, pickle.PicklingError)):
129 pickle.dumps(g, proto)
130
Victor Stinner40ee3012014-06-16 15:59:28 +0200131
Victor Stinner26f7b8a2015-01-31 10:29:47 +0100132class ExceptionTest(unittest.TestCase):
133 # Tests for the issue #23353: check that the currently handled exception
134 # is correctly saved/restored in PyEval_EvalFrameEx().
135
136 def test_except_throw(self):
137 def store_raise_exc_generator():
138 try:
139 self.assertEqual(sys.exc_info()[0], None)
140 yield
141 except Exception as exc:
142 # exception raised by gen.throw(exc)
143 self.assertEqual(sys.exc_info()[0], ValueError)
144 self.assertIsNone(exc.__context__)
145 yield
146
147 # ensure that the exception is not lost
148 self.assertEqual(sys.exc_info()[0], ValueError)
149 yield
150
151 # we should be able to raise back the ValueError
152 raise
153
154 make = store_raise_exc_generator()
155 next(make)
156
157 try:
158 raise ValueError()
159 except Exception as exc:
160 try:
161 make.throw(exc)
162 except Exception:
163 pass
164
165 next(make)
166 with self.assertRaises(ValueError) as cm:
167 next(make)
168 self.assertIsNone(cm.exception.__context__)
169
170 self.assertEqual(sys.exc_info(), (None, None, None))
171
172 def test_except_next(self):
173 def gen():
174 self.assertEqual(sys.exc_info()[0], ValueError)
175 yield "done"
176
177 g = gen()
178 try:
179 raise ValueError
180 except Exception:
181 self.assertEqual(next(g), "done")
182 self.assertEqual(sys.exc_info(), (None, None, None))
183
184 def test_except_gen_except(self):
185 def gen():
186 try:
187 self.assertEqual(sys.exc_info()[0], None)
188 yield
189 # we are called from "except ValueError:", TypeError must
190 # inherit ValueError in its context
191 raise TypeError()
192 except TypeError as exc:
193 self.assertEqual(sys.exc_info()[0], TypeError)
194 self.assertEqual(type(exc.__context__), ValueError)
195 # here we are still called from the "except ValueError:"
196 self.assertEqual(sys.exc_info()[0], ValueError)
197 yield
198 self.assertIsNone(sys.exc_info()[0])
199 yield "done"
200
201 g = gen()
202 next(g)
203 try:
204 raise ValueError
205 except Exception:
206 next(g)
207
208 self.assertEqual(next(g), "done")
209 self.assertEqual(sys.exc_info(), (None, None, None))
210
211 def test_except_throw_exception_context(self):
212 def gen():
213 try:
214 try:
215 self.assertEqual(sys.exc_info()[0], None)
216 yield
217 except ValueError:
218 # we are called from "except ValueError:"
219 self.assertEqual(sys.exc_info()[0], ValueError)
220 raise TypeError()
221 except Exception as exc:
222 self.assertEqual(sys.exc_info()[0], TypeError)
223 self.assertEqual(type(exc.__context__), ValueError)
224 # we are still called from "except ValueError:"
225 self.assertEqual(sys.exc_info()[0], ValueError)
226 yield
227 self.assertIsNone(sys.exc_info()[0])
228 yield "done"
229
230 g = gen()
231 next(g)
232 try:
233 raise ValueError
234 except Exception as exc:
235 g.throw(exc)
236
237 self.assertEqual(next(g), "done")
238 self.assertEqual(sys.exc_info(), (None, None, None))
239
Yury Selivanov68333392015-05-22 11:16:47 -0400240 def test_stopiteration_warning(self):
241 # See also PEP 479.
242
243 def gen():
244 raise StopIteration
245 yield
246
247 with self.assertRaises(StopIteration), \
248 self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"):
249
250 next(gen())
251
252 with self.assertRaisesRegex(PendingDeprecationWarning,
253 "generator .* raised StopIteration"), \
254 warnings.catch_warnings():
255
256 warnings.simplefilter('error')
257 next(gen())
258
259
260 def test_tutorial_stopiteration(self):
261 # Raise StopIteration" stops the generator too:
262
263 def f():
264 yield 1
265 raise StopIteration
266 yield 2 # never reached
267
268 g = f()
269 self.assertEqual(next(g), 1)
270
271 with self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"):
272 with self.assertRaises(StopIteration):
273 next(g)
274
275 with self.assertRaises(StopIteration):
276 # This time StopIteration isn't raised from the generator's body,
277 # hence no warning.
278 next(g)
279
Victor Stinner26f7b8a2015-01-31 10:29:47 +0100280
Yury Selivanove13f8f32015-07-03 00:23:30 -0400281class YieldFromTests(unittest.TestCase):
282 def test_generator_gi_yieldfrom(self):
283 def a():
284 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING)
285 self.assertIsNone(gen_b.gi_yieldfrom)
286 yield
287 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING)
288 self.assertIsNone(gen_b.gi_yieldfrom)
289
290 def b():
291 self.assertIsNone(gen_b.gi_yieldfrom)
292 yield from a()
293 self.assertIsNone(gen_b.gi_yieldfrom)
294 yield
295 self.assertIsNone(gen_b.gi_yieldfrom)
296
297 gen_b = b()
298 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CREATED)
299 self.assertIsNone(gen_b.gi_yieldfrom)
300
301 gen_b.send(None)
302 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED)
303 self.assertEqual(gen_b.gi_yieldfrom.gi_code.co_name, 'a')
304
305 gen_b.send(None)
306 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED)
307 self.assertIsNone(gen_b.gi_yieldfrom)
308
309 [] = gen_b # Exhaust generator
310 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CLOSED)
311 self.assertIsNone(gen_b.gi_yieldfrom)
312
313
Tim Peters6ba5f792001-06-23 20:45:43 +0000314tutorial_tests = """
Tim Peters1def3512001-06-23 20:27:04 +0000315Let's try a simple generator:
316
317 >>> def f():
318 ... yield 1
319 ... yield 2
320
Tim Petersb9e9ff12001-06-24 03:44:52 +0000321 >>> for i in f():
Guido van Rossum7131f842007-02-09 20:13:25 +0000322 ... print(i)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000323 1
324 2
Tim Peters1def3512001-06-23 20:27:04 +0000325 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000326 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000327 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000328 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000329 2
Tim Petersea2e97a2001-06-24 07:10:02 +0000330
Tim Peters2106ef02001-06-25 01:30:12 +0000331"Falling off the end" stops the generator:
Tim Petersea2e97a2001-06-24 07:10:02 +0000332
Georg Brandla18af4e2007-04-21 15:47:16 +0000333 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000334 Traceback (most recent call last):
335 File "<stdin>", line 1, in ?
336 File "<stdin>", line 2, in g
337 StopIteration
338
Tim Petersea2e97a2001-06-24 07:10:02 +0000339"return" also stops the generator:
Tim Peters1def3512001-06-23 20:27:04 +0000340
341 >>> def f():
342 ... yield 1
343 ... return
344 ... yield 2 # never reached
345 ...
346 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000347 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000348 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000349 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000350 Traceback (most recent call last):
351 File "<stdin>", line 1, in ?
352 File "<stdin>", line 3, in f
353 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +0000354 >>> next(g) # once stopped, can't be resumed
Tim Peters1def3512001-06-23 20:27:04 +0000355 Traceback (most recent call last):
356 File "<stdin>", line 1, in ?
357 StopIteration
358
Yury Selivanov68333392015-05-22 11:16:47 -0400359However, "return" and StopIteration are not exactly equivalent:
Tim Peters1def3512001-06-23 20:27:04 +0000360
361 >>> def g1():
362 ... try:
363 ... return
364 ... except:
365 ... yield 1
366 ...
367 >>> list(g1())
368 []
369
370 >>> def g2():
371 ... try:
372 ... raise StopIteration
373 ... except:
374 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000375 >>> print(list(g2()))
Tim Peters1def3512001-06-23 20:27:04 +0000376 [42]
377
378This may be surprising at first:
379
380 >>> def g3():
381 ... try:
382 ... return
383 ... finally:
384 ... yield 1
385 ...
386 >>> list(g3())
387 [1]
388
389Let's create an alternate range() function implemented as a generator:
390
391 >>> def yrange(n):
392 ... for i in range(n):
393 ... yield i
394 ...
395 >>> list(yrange(5))
396 [0, 1, 2, 3, 4]
397
398Generators always return to the most recent caller:
399
400 >>> def creator():
401 ... r = yrange(5)
Georg Brandla18af4e2007-04-21 15:47:16 +0000402 ... print("creator", next(r))
Tim Peters1def3512001-06-23 20:27:04 +0000403 ... return r
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000404 ...
Tim Peters1def3512001-06-23 20:27:04 +0000405 >>> def caller():
406 ... r = creator()
407 ... for i in r:
Guido van Rossum7131f842007-02-09 20:13:25 +0000408 ... print("caller", i)
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000409 ...
Tim Peters1def3512001-06-23 20:27:04 +0000410 >>> caller()
411 creator 0
412 caller 1
413 caller 2
414 caller 3
415 caller 4
416
417Generators can call other generators:
418
419 >>> def zrange(n):
420 ... for i in yrange(n):
421 ... yield i
422 ...
423 >>> list(zrange(5))
424 [0, 1, 2, 3, 4]
425
426"""
427
Tim Peters6ba5f792001-06-23 20:45:43 +0000428# The examples from PEP 255.
429
430pep_tests = """
431
Tim Peterse5614632001-08-15 04:41:19 +0000432Specification: Yield
433
434 Restriction: A generator cannot be resumed while it is actively
435 running:
436
437 >>> def g():
Georg Brandla18af4e2007-04-21 15:47:16 +0000438 ... i = next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000439 ... yield i
440 >>> me = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000441 >>> next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000442 Traceback (most recent call last):
443 ...
444 File "<string>", line 2, in g
445 ValueError: generator already executing
446
Tim Peters6ba5f792001-06-23 20:45:43 +0000447Specification: Return
448
449 Note that return isn't always equivalent to raising StopIteration: the
450 difference lies in how enclosing try/except constructs are treated.
451 For example,
452
453 >>> def f1():
454 ... try:
455 ... return
456 ... except:
457 ... yield 1
Guido van Rossum7131f842007-02-09 20:13:25 +0000458 >>> print(list(f1()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000459 []
460
461 because, as in any function, return simply exits, but
462
463 >>> def f2():
464 ... try:
465 ... raise StopIteration
466 ... except:
467 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000468 >>> print(list(f2()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000469 [42]
470
471 because StopIteration is captured by a bare "except", as is any
472 exception.
473
474Specification: Generators and Exception Propagation
475
476 >>> def f():
Tim Peters3caca232001-12-06 06:23:26 +0000477 ... return 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000478 >>> def g():
479 ... yield f() # the zero division exception propagates
480 ... yield 42 # and we'll never get here
481 >>> k = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000482 >>> next(k)
Tim Peters6ba5f792001-06-23 20:45:43 +0000483 Traceback (most recent call last):
484 File "<stdin>", line 1, in ?
485 File "<stdin>", line 2, in g
486 File "<stdin>", line 2, in f
487 ZeroDivisionError: integer division or modulo by zero
Georg Brandla18af4e2007-04-21 15:47:16 +0000488 >>> next(k) # and the generator cannot be resumed
Tim Peters6ba5f792001-06-23 20:45:43 +0000489 Traceback (most recent call last):
490 File "<stdin>", line 1, in ?
491 StopIteration
492 >>>
493
494Specification: Try/Except/Finally
495
496 >>> def f():
497 ... try:
498 ... yield 1
499 ... try:
500 ... yield 2
Tim Peters3caca232001-12-06 06:23:26 +0000501 ... 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000502 ... yield 3 # never get here
503 ... except ZeroDivisionError:
504 ... yield 4
505 ... yield 5
506 ... raise
507 ... except:
508 ... yield 6
509 ... yield 7 # the "raise" above stops this
510 ... except:
511 ... yield 8
512 ... yield 9
513 ... try:
514 ... x = 12
515 ... finally:
516 ... yield 10
517 ... yield 11
Guido van Rossum7131f842007-02-09 20:13:25 +0000518 >>> print(list(f()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000519 [1, 2, 4, 5, 8, 9, 10, 11]
520 >>>
521
Tim Peters6ba5f792001-06-23 20:45:43 +0000522Guido's binary tree example.
523
524 >>> # A binary tree class.
525 >>> class Tree:
526 ...
527 ... def __init__(self, label, left=None, right=None):
528 ... self.label = label
529 ... self.left = left
530 ... self.right = right
531 ...
532 ... def __repr__(self, level=0, indent=" "):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000533 ... s = level*indent + repr(self.label)
Tim Peters6ba5f792001-06-23 20:45:43 +0000534 ... if self.left:
535 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
536 ... if self.right:
537 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
538 ... return s
539 ...
540 ... def __iter__(self):
541 ... return inorder(self)
542
543 >>> # Create a Tree from a list.
544 >>> def tree(list):
545 ... n = len(list)
546 ... if n == 0:
547 ... return []
Tim Peters3caca232001-12-06 06:23:26 +0000548 ... i = n // 2
Tim Peters6ba5f792001-06-23 20:45:43 +0000549 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
550
551 >>> # Show it off: create a tree.
552 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
553
Tim Petersd674e172002-03-10 07:59:13 +0000554 >>> # A recursive generator that generates Tree labels in in-order.
Tim Peters6ba5f792001-06-23 20:45:43 +0000555 >>> def inorder(t):
556 ... if t:
557 ... for x in inorder(t.left):
558 ... yield x
559 ... yield t.label
560 ... for x in inorder(t.right):
561 ... yield x
562
563 >>> # Show it off: create a tree.
Edward Loper103d26e2004-08-09 02:03:30 +0000564 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
565 >>> # Print the nodes of the tree in in-order.
566 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000567 ... print(' '+x, end='')
568 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 +0000569
570 >>> # A non-recursive generator.
571 >>> def inorder(node):
572 ... stack = []
573 ... while node:
574 ... while node.left:
575 ... stack.append(node)
576 ... node = node.left
577 ... yield node.label
578 ... while not node.right:
579 ... try:
580 ... node = stack.pop()
581 ... except IndexError:
582 ... return
583 ... yield node.label
584 ... node = node.right
585
586 >>> # Exercise the non-recursive generator.
587 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000588 ... print(' '+x, end='')
589 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 +0000590
591"""
592
Tim Petersb2bc6a92001-06-24 10:14:27 +0000593# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000594
595email_tests = """
596
597The difference between yielding None and returning it.
598
599>>> def g():
600... for i in range(3):
601... yield None
602... yield None
603... return
604>>> list(g())
605[None, None, None, None]
606
607Ensure that explicitly raising StopIteration acts like any other exception
608in try/except, not like a return.
609
610>>> def g():
611... yield 1
612... try:
613... raise StopIteration
614... except:
615... yield 2
616... yield 3
617>>> list(g())
618[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000619
Tim Petersb2bc6a92001-06-24 10:14:27 +0000620Next one was posted to c.l.py.
621
622>>> def gcomb(x, k):
623... "Generate all combinations of k elements from list x."
624...
625... if k > len(x):
626... return
627... if k == 0:
628... yield []
629... else:
630... first, rest = x[0], x[1:]
631... # A combination does or doesn't contain first.
632... # If it does, the remainder is a k-1 comb of rest.
633... for c in gcomb(rest, k-1):
634... c.insert(0, first)
635... yield c
636... # If it doesn't contain first, it's a k comb of rest.
637... for c in gcomb(rest, k):
638... yield c
639
Guido van Rossum805365e2007-05-07 22:24:25 +0000640>>> seq = list(range(1, 5))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000641>>> for k in range(len(seq) + 2):
Guido van Rossum7131f842007-02-09 20:13:25 +0000642... print("%d-combs of %s:" % (k, seq))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000643... for c in gcomb(seq, k):
Guido van Rossum7131f842007-02-09 20:13:25 +0000644... print(" ", c)
Tim Petersb2bc6a92001-06-24 10:14:27 +00006450-combs of [1, 2, 3, 4]:
646 []
6471-combs of [1, 2, 3, 4]:
648 [1]
649 [2]
650 [3]
651 [4]
6522-combs of [1, 2, 3, 4]:
653 [1, 2]
654 [1, 3]
655 [1, 4]
656 [2, 3]
657 [2, 4]
658 [3, 4]
6593-combs of [1, 2, 3, 4]:
660 [1, 2, 3]
661 [1, 2, 4]
662 [1, 3, 4]
663 [2, 3, 4]
6644-combs of [1, 2, 3, 4]:
665 [1, 2, 3, 4]
6665-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000667
Tim Peterse77f2e22001-06-26 22:24:51 +0000668From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000669
670>>> def g():
671... yield 1
672...
673>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000674<class 'function'>
Tim Peters3e7b1a02001-06-25 19:46:25 +0000675>>> i = g()
676>>> type(i)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000677<class 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000678>>> [s for s in dir(i) if not s.startswith('_')]
Yury Selivanove13f8f32015-07-03 00:23:30 -0400679['close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
Serhiy Storchaka9a11f172013-01-31 16:11:04 +0200680>>> from test.support import HAVE_DOCSTRINGS
Larry Hastings581ee362014-01-28 05:00:08 -0800681>>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).')
682Implement next(self).
Tim Peters3e7b1a02001-06-25 19:46:25 +0000683>>> iter(i) is i
Guido van Rossum77f6a652002-04-03 22:41:51 +0000684True
Tim Peters3e7b1a02001-06-25 19:46:25 +0000685>>> import types
686>>> isinstance(i, types.GeneratorType)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000687True
Tim Peterse77f2e22001-06-26 22:24:51 +0000688
689And more, added later.
690
691>>> i.gi_running
6920
693>>> type(i.gi_frame)
Martin v. Löwis250ad612008-04-07 05:43:42 +0000694<class 'frame'>
Tim Peterse77f2e22001-06-26 22:24:51 +0000695>>> i.gi_running = 42
696Traceback (most recent call last):
697 ...
Collin Winter42dae6a2007-03-28 21:44:53 +0000698AttributeError: readonly attribute
Tim Peterse77f2e22001-06-26 22:24:51 +0000699>>> def g():
700... yield me.gi_running
701>>> me = g()
702>>> me.gi_running
7030
Georg Brandla18af4e2007-04-21 15:47:16 +0000704>>> next(me)
Tim Peterse77f2e22001-06-26 22:24:51 +00007051
706>>> me.gi_running
7070
Tim Peters35302662001-07-02 01:38:33 +0000708
709A clever union-find implementation from c.l.py, due to David Eppstein.
710Sent: Friday, June 29, 2001 12:16 PM
711To: python-list@python.org
712Subject: Re: PEP 255: Simple Generators
713
714>>> class disjointSet:
715... def __init__(self, name):
716... self.name = name
717... self.parent = None
718... self.generator = self.generate()
719...
720... def generate(self):
721... while not self.parent:
722... yield self
723... for x in self.parent.generator:
724... yield x
725...
726... def find(self):
Georg Brandla18af4e2007-04-21 15:47:16 +0000727... return next(self.generator)
Tim Peters35302662001-07-02 01:38:33 +0000728...
729... def union(self, parent):
730... if self.parent:
731... raise ValueError("Sorry, I'm not a root!")
732... self.parent = parent
733...
734... def __str__(self):
735... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000736
737>>> names = "ABCDEFGHIJKLM"
738>>> sets = [disjointSet(name) for name in names]
739>>> roots = sets[:]
740
741>>> import random
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000742>>> gen = random.Random(42)
Tim Peters35302662001-07-02 01:38:33 +0000743>>> while 1:
744... for s in sets:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000745... print(" %s->%s" % (s, s.find()), end='')
Guido van Rossum7131f842007-02-09 20:13:25 +0000746... print()
Tim Peters35302662001-07-02 01:38:33 +0000747... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000748... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000749... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000750... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000751... s1.union(s2)
Guido van Rossum7131f842007-02-09 20:13:25 +0000752... print("merged", s1, "into", s2)
Tim Peters35302662001-07-02 01:38:33 +0000753... else:
754... break
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000755 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 +0000756merged K into B
757 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 +0000758merged A into F
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000759 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
760merged E into F
761 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
762merged D into C
763 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 +0000764merged M into C
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000765 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
766merged J into B
767 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
768merged B into C
769 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
770merged F into G
771 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
772merged L into C
773 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
774merged G into I
775 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
776merged I into H
777 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
778merged C into H
779 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 +0000780
Tim Peters6ba5f792001-06-23 20:45:43 +0000781"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000782# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000783
Tim Peters0f9da0a2001-06-23 21:01:47 +0000784# Fun tests (for sufficiently warped notions of "fun").
785
786fun_tests = """
787
788Build up to a recursive Sieve of Eratosthenes generator.
789
790>>> def firstn(g, n):
Georg Brandla18af4e2007-04-21 15:47:16 +0000791... return [next(g) for i in range(n)]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000792
793>>> def intsfrom(i):
794... while 1:
795... yield i
796... i += 1
797
798>>> firstn(intsfrom(5), 7)
799[5, 6, 7, 8, 9, 10, 11]
800
801>>> def exclude_multiples(n, ints):
802... for i in ints:
803... if i % n:
804... yield i
805
806>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
807[1, 2, 4, 5, 7, 8]
808
809>>> def sieve(ints):
Georg Brandla18af4e2007-04-21 15:47:16 +0000810... prime = next(ints)
Tim Peters0f9da0a2001-06-23 21:01:47 +0000811... yield prime
812... not_divisible_by_prime = exclude_multiples(prime, ints)
813... for p in sieve(not_divisible_by_prime):
814... yield p
815
816>>> primes = sieve(intsfrom(2))
817>>> firstn(primes, 20)
818[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 +0000819
Tim Petersf6ed0742001-06-27 07:17:57 +0000820
Tim Petersb9e9ff12001-06-24 03:44:52 +0000821Another famous problem: generate all integers of the form
822 2**i * 3**j * 5**k
823in increasing order, where i,j,k >= 0. Trickier than it may look at first!
824Try writing it without generators, and correctly, and without generating
8253 internal results for each result output.
826
827>>> def times(n, g):
828... for i in g:
829... yield n * i
830>>> firstn(times(10, intsfrom(1)), 10)
831[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
832
833>>> def merge(g, h):
Georg Brandla18af4e2007-04-21 15:47:16 +0000834... ng = next(g)
835... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000836... while 1:
837... if ng < nh:
838... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000839... ng = next(g)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000840... elif ng > nh:
841... yield nh
Georg Brandla18af4e2007-04-21 15:47:16 +0000842... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000843... else:
844... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000845... ng = next(g)
846... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000847
Tim Petersf6ed0742001-06-27 07:17:57 +0000848The following works, but is doing a whale of a lot of redundant work --
849it's not clear how to get the internal uses of m235 to share a single
850generator. Note that me_times2 (etc) each need to see every element in the
851result sequence. So this is an example where lazy lists are more natural
852(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000853
854>>> def m235():
855... yield 1
856... me_times2 = times(2, m235())
857... me_times3 = times(3, m235())
858... me_times5 = times(5, m235())
859... for i in merge(merge(me_times2,
860... me_times3),
861... me_times5):
862... yield i
863
Tim Petersf6ed0742001-06-27 07:17:57 +0000864Don't print "too many" of these -- the implementation above is extremely
865inefficient: each call of m235() leads to 3 recursive calls, and in
866turn each of those 3 more, and so on, and so on, until we've descended
867enough levels to satisfy the print stmts. Very odd: when I printed 5
868lines of results below, this managed to screw up Win98's malloc in "the
869usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
870address space, and it *looked* like a very slow leak.
871
Tim Petersb9e9ff12001-06-24 03:44:52 +0000872>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000873>>> for i in range(3):
Guido van Rossum7131f842007-02-09 20:13:25 +0000874... print(firstn(result, 15))
Tim Petersb9e9ff12001-06-24 03:44:52 +0000875[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
876[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
877[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000878
879Heh. Here's one way to get a shared list, complete with an excruciating
880namespace renaming trick. The *pretty* part is that the times() and merge()
881functions can be reused as-is, because they only assume their stream
882arguments are iterable -- a LazyList is the same as a generator to times().
883
884>>> class LazyList:
885... def __init__(self, g):
886... self.sofar = []
Georg Brandla18af4e2007-04-21 15:47:16 +0000887... self.fetch = g.__next__
Tim Petersee309272001-06-24 05:47:06 +0000888...
889... def __getitem__(self, i):
890... sofar, fetch = self.sofar, self.fetch
891... while i >= len(sofar):
892... sofar.append(fetch())
893... return sofar[i]
894
895>>> def m235():
896... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000897... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000898... me_times2 = times(2, m235)
899... me_times3 = times(3, m235)
900... me_times5 = times(5, m235)
901... for i in merge(merge(me_times2,
902... me_times3),
903... me_times5):
904... yield i
905
Tim Petersf6ed0742001-06-27 07:17:57 +0000906Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000907efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000908
Tim Petersee309272001-06-24 05:47:06 +0000909>>> m235 = LazyList(m235())
910>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000911... print([m235[j] for j in range(15*i, 15*(i+1))])
Tim Petersee309272001-06-24 05:47:06 +0000912[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
913[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
914[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
915[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
916[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000917
Tim Petersf6ed0742001-06-27 07:17:57 +0000918Ye olde Fibonacci generator, LazyList style.
919
920>>> def fibgen(a, b):
921...
922... def sum(g, h):
923... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000924... yield next(g) + next(h)
Tim Petersf6ed0742001-06-27 07:17:57 +0000925...
926... def tail(g):
Georg Brandla18af4e2007-04-21 15:47:16 +0000927... next(g) # throw first away
Tim Petersf6ed0742001-06-27 07:17:57 +0000928... for x in g:
929... yield x
930...
931... yield a
932... yield b
933... for s in sum(iter(fib),
934... tail(iter(fib))):
935... yield s
936
937>>> fib = LazyList(fibgen(1, 2))
938>>> firstn(iter(fib), 17)
939[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Georg Brandl52715f62005-08-24 09:02:29 +0000940
941
942Running after your tail with itertools.tee (new in version 2.4)
943
944The algorithms "m235" (Hamming) and Fibonacci presented above are both
945examples of a whole family of FP (functional programming) algorithms
946where a function produces and returns a list while the production algorithm
947suppose the list as already produced by recursively calling itself.
948For these algorithms to work, they must:
949
950- produce at least a first element without presupposing the existence of
951 the rest of the list
952- produce their elements in a lazy manner
953
954To work efficiently, the beginning of the list must not be recomputed over
955and over again. This is ensured in most FP languages as a built-in feature.
956In python, we have to explicitly maintain a list of already computed results
957and abandon genuine recursivity.
958
959This is what had been attempted above with the LazyList class. One problem
960with that class is that it keeps a list of all of the generated results and
961therefore continually grows. This partially defeats the goal of the generator
962concept, viz. produce the results only as needed instead of producing them
963all and thereby wasting memory.
964
965Thanks to itertools.tee, it is now clear "how to get the internal uses of
966m235 to share a single generator".
967
968>>> from itertools import tee
969>>> def m235():
970... def _m235():
971... yield 1
972... for n in merge(times(2, m2),
973... merge(times(3, m3),
974... times(5, m5))):
975... yield n
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000976... m1 = _m235()
977... m2, m3, m5, mRes = tee(m1, 4)
Georg Brandl52715f62005-08-24 09:02:29 +0000978... return mRes
979
980>>> it = m235()
981>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000982... print(firstn(it, 15))
Georg Brandl52715f62005-08-24 09:02:29 +0000983[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
984[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
985[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
986[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
987[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
988
989The "tee" function does just what we want. It internally keeps a generated
990result for as long as it has not been "consumed" from all of the duplicated
991iterators, whereupon it is deleted. You can therefore print the hamming
992sequence during hours without increasing memory usage, or very little.
993
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000994The beauty of it is that recursive running-after-their-tail FP algorithms
Georg Brandl52715f62005-08-24 09:02:29 +0000995are quite straightforwardly expressed with this Python idiom.
996
Georg Brandl52715f62005-08-24 09:02:29 +0000997Ye olde Fibonacci generator, tee style.
998
999>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +00001000...
Georg Brandl52715f62005-08-24 09:02:29 +00001001... def _isum(g, h):
1002... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +00001003... yield next(g) + next(h)
Tim Peters9e34c042005-08-26 15:20:46 +00001004...
Georg Brandl52715f62005-08-24 09:02:29 +00001005... def _fib():
1006... yield 1
1007... yield 2
Georg Brandla18af4e2007-04-21 15:47:16 +00001008... next(fibTail) # throw first away
Georg Brandl52715f62005-08-24 09:02:29 +00001009... for res in _isum(fibHead, fibTail):
1010... yield res
Tim Peters9e34c042005-08-26 15:20:46 +00001011...
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001012... realfib = _fib()
1013... fibHead, fibTail, fibRes = tee(realfib, 3)
Georg Brandl52715f62005-08-24 09:02:29 +00001014... return fibRes
1015
1016>>> firstn(fib(), 17)
1017[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
1018
Tim Peters0f9da0a2001-06-23 21:01:47 +00001019"""
1020
Tim Petersb6c3cea2001-06-26 03:36:28 +00001021# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
1022# hackery.
Tim Petersee309272001-06-24 05:47:06 +00001023
Tim Petersea2e97a2001-06-24 07:10:02 +00001024syntax_tests = """
1025
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001026These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +00001027
1028>>> def f():
1029... yield 1
1030... return
1031
Tim Petersaef8cfa2004-08-27 15:12:49 +00001032>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +00001033... try:
1034... yield 1
1035... finally:
1036... pass
Tim Petersea2e97a2001-06-24 07:10:02 +00001037
Tim Petersaef8cfa2004-08-27 15:12:49 +00001038>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +00001039... try:
1040... try:
Tim Peters3caca232001-12-06 06:23:26 +00001041... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +00001042... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +00001043... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +00001044... except:
1045... pass
1046... finally:
1047... pass
Tim Petersea2e97a2001-06-24 07:10:02 +00001048
1049>>> def f():
1050... try:
1051... try:
1052... yield 12
Tim Peters3caca232001-12-06 06:23:26 +00001053... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +00001054... except ZeroDivisionError:
1055... yield 666
1056... except:
1057... try:
1058... x = 12
1059... finally:
1060... yield 12
1061... except:
1062... return
1063>>> list(f())
1064[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +00001065
1066>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +00001067... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001068>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001069<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001070
Tim Peters08a898f2001-06-28 01:52:22 +00001071
1072>>> def f():
1073... if 0:
1074... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001075>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001076<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001077
Tim Peters08a898f2001-06-28 01:52:22 +00001078
1079>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +00001080... if 0:
1081... yield 1
1082>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001083<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001084
1085>>> def f():
1086... if "":
1087... yield None
1088>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001089<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001090
1091>>> def f():
1092... return
1093... try:
1094... if x==4:
1095... pass
1096... elif 0:
1097... try:
Tim Peters3caca232001-12-06 06:23:26 +00001098... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +00001099... except SyntaxError:
1100... pass
1101... else:
1102... if 0:
1103... while 12:
1104... x += 1
1105... yield 2 # don't blink
1106... f(a, b, c, d, e)
1107... else:
1108... pass
1109... except:
1110... x = 1
1111... return
1112>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001113<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001114
1115>>> def f():
1116... if 0:
1117... def g():
1118... yield 1
1119...
1120>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001121<class 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001122
1123>>> def f():
1124... if 0:
1125... class C:
1126... def __init__(self):
1127... yield 1
1128... def f(self):
1129... yield 2
1130>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001131<class 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +00001132
1133>>> def f():
1134... if 0:
1135... return
1136... if 0:
1137... yield 2
1138>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001139<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +00001140
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001141This one caused a crash (see SF bug 567538):
1142
1143>>> def f():
1144... for i in range(3):
1145... try:
1146... continue
1147... finally:
1148... yield i
Tim Petersc411dba2002-07-16 21:35:23 +00001149...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001150>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001151>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000011520
Georg Brandla18af4e2007-04-21 15:47:16 +00001153>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000011541
Georg Brandla18af4e2007-04-21 15:47:16 +00001155>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000011562
Georg Brandla18af4e2007-04-21 15:47:16 +00001157>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001158Traceback (most recent call last):
1159StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +00001160
1161
1162Test the gi_code attribute
1163
1164>>> def f():
1165... yield 5
1166...
1167>>> g = f()
1168>>> g.gi_code is f.__code__
1169True
1170>>> next(g)
11715
1172>>> next(g)
1173Traceback (most recent call last):
1174StopIteration
1175>>> g.gi_code is f.__code__
1176True
1177
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +00001178
1179Test the __name__ attribute and the repr()
1180
1181>>> def f():
1182... yield 5
1183...
1184>>> g = f()
1185>>> g.__name__
1186'f'
1187>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +00001188'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +00001189
1190Lambdas shouldn't have their usual return behavior.
1191
1192>>> x = lambda: (yield 1)
1193>>> list(x())
1194[1]
1195
1196>>> x = lambda: ((yield 1), (yield 2))
1197>>> list(x())
1198[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +00001199"""
1200
Tim Petersbe4f0a72001-06-29 02:41:16 +00001201# conjoin is a simple backtracking generator, named in honor of Icon's
1202# "conjunction" control structure. Pass a list of no-argument functions
1203# that return iterable objects. Easiest to explain by example: assume the
1204# function list [x, y, z] is passed. Then conjoin acts like:
1205#
1206# def g():
1207# values = [None] * 3
1208# for values[0] in x():
1209# for values[1] in y():
1210# for values[2] in z():
1211# yield values
1212#
1213# So some 3-lists of values *may* be generated, each time we successfully
1214# get into the innermost loop. If an iterator fails (is exhausted) before
1215# then, it "backtracks" to get the next value from the nearest enclosing
1216# iterator (the one "to the left"), and starts all over again at the next
1217# slot (pumps a fresh iterator). Of course this is most useful when the
1218# iterators have side-effects, so that which values *can* be generated at
1219# each slot depend on the values iterated at previous slots.
1220
Benjamin Peterson78565b22009-06-28 19:19:51 +00001221def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001222
1223 values = [None] * len(gs)
1224
Benjamin Peterson78565b22009-06-28 19:19:51 +00001225 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001226 if i >= len(gs):
1227 yield values
1228 else:
1229 for values[i] in gs[i]():
1230 for x in gen(i+1):
1231 yield x
1232
1233 for x in gen(0):
1234 yield x
1235
Tim Petersc468fd22001-06-30 07:29:44 +00001236# That works fine, but recursing a level and checking i against len(gs) for
1237# each item produced is inefficient. By doing manual loop unrolling across
1238# generator boundaries, it's possible to eliminate most of that overhead.
1239# This isn't worth the bother *in general* for generators, but conjoin() is
1240# a core building block for some CPU-intensive generator applications.
1241
1242def conjoin(gs):
1243
1244 n = len(gs)
1245 values = [None] * n
1246
1247 # Do one loop nest at time recursively, until the # of loop nests
1248 # remaining is divisible by 3.
1249
Benjamin Peterson78565b22009-06-28 19:19:51 +00001250 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001251 if i >= n:
1252 yield values
1253
1254 elif (n-i) % 3:
1255 ip1 = i+1
1256 for values[i] in gs[i]():
1257 for x in gen(ip1):
1258 yield x
1259
1260 else:
1261 for x in _gen3(i):
1262 yield x
1263
1264 # Do three loop nests at a time, recursing only if at least three more
1265 # remain. Don't call directly: this is an internal optimization for
1266 # gen's use.
1267
Benjamin Peterson78565b22009-06-28 19:19:51 +00001268 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001269 assert i < n and (n-i) % 3 == 0
1270 ip1, ip2, ip3 = i+1, i+2, i+3
1271 g, g1, g2 = gs[i : ip3]
1272
1273 if ip3 >= n:
1274 # These are the last three, so we can yield values directly.
1275 for values[i] in g():
1276 for values[ip1] in g1():
1277 for values[ip2] in g2():
1278 yield values
1279
1280 else:
1281 # At least 6 loop nests remain; peel off 3 and recurse for the
1282 # rest.
1283 for values[i] in g():
1284 for values[ip1] in g1():
1285 for values[ip2] in g2():
1286 for x in _gen3(ip3):
1287 yield x
1288
1289 for x in gen(0):
1290 yield x
1291
unknown31569562001-07-04 22:11:22 +00001292# And one more approach: For backtracking apps like the Knight's Tour
1293# solver below, the number of backtracking levels can be enormous (one
1294# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1295# needs 10,000 levels). In such cases Python is likely to run out of
1296# stack space due to recursion. So here's a recursion-free version of
1297# conjoin too.
1298# NOTE WELL: This allows large problems to be solved with only trivial
1299# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001300# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1301# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001302
1303def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1304 n = len(gs)
1305 values = [None] * n
1306 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001307 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001308 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001309 while 1:
1310 # Descend.
1311 try:
1312 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001313 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001314 values[i] = it()
1315 i += 1
1316 except _StopIteration:
1317 pass
unknown31569562001-07-04 22:11:22 +00001318 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001319 assert i == n
1320 yield values
unknown31569562001-07-04 22:11:22 +00001321
Tim Peters9a8c8e22001-07-13 09:12:12 +00001322 # Backtrack until an older iterator can be resumed.
1323 i -= 1
unknown31569562001-07-04 22:11:22 +00001324 while i >= 0:
1325 try:
1326 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001327 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001328 i += 1
1329 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001330 except _StopIteration:
1331 # Continue backtracking.
1332 i -= 1
1333 else:
1334 assert i < 0
1335 break
unknown31569562001-07-04 22:11:22 +00001336
Tim Petersbe4f0a72001-06-29 02:41:16 +00001337# A conjoin-based N-Queens solver.
1338
1339class Queens:
1340 def __init__(self, n):
1341 self.n = n
1342 rangen = range(n)
1343
1344 # Assign a unique int to each column and diagonal.
1345 # columns: n of those, range(n).
1346 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1347 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1348 # based.
1349 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1350 # each, smallest i+j is 0, largest is 2n-2.
1351
1352 # For each square, compute a bit vector of the columns and
1353 # diagonals it covers, and for each row compute a function that
Martin Panter46f50722016-05-26 05:35:26 +00001354 # generates the possibilities for the columns in that row.
Tim Petersbe4f0a72001-06-29 02:41:16 +00001355 self.rowgenerators = []
1356 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001357 rowuses = [(1 << j) | # column ordinal
1358 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1359 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001360 for j in rangen]
1361
1362 def rowgen(rowuses=rowuses):
1363 for j in rangen:
1364 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001365 if uses & self.used == 0:
1366 self.used |= uses
1367 yield j
1368 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001369
1370 self.rowgenerators.append(rowgen)
1371
1372 # Generate solutions.
1373 def solve(self):
1374 self.used = 0
1375 for row2col in conjoin(self.rowgenerators):
1376 yield row2col
1377
1378 def printsolution(self, row2col):
1379 n = self.n
1380 assert n == len(row2col)
1381 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001382 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001383 for i in range(n):
1384 squares = [" " for j in range(n)]
1385 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001386 print("|" + "|".join(squares) + "|")
1387 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001388
unknown31569562001-07-04 22:11:22 +00001389# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1390# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1391# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001392# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001393
1394class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001395 def __init__(self, m, n, hard=0):
1396 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001397
Tim Peters9a8c8e22001-07-13 09:12:12 +00001398 # solve() will set up succs[i] to be a list of square #i's
1399 # successors.
1400 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001401
Tim Peters9a8c8e22001-07-13 09:12:12 +00001402 # Remove i0 from each of its successor's successor lists, i.e.
1403 # successors can't go back to i0 again. Return 0 if we can
1404 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001405
Tim Peters9a8c8e22001-07-13 09:12:12 +00001406 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001407 # If we remove all exits from a free square, we're dead:
1408 # even if we move to it next, we can't leave it again.
1409 # If we create a square with one exit, we must visit it next;
1410 # else somebody else will have to visit it, and since there's
1411 # only one adjacent, there won't be a way to leave it again.
1412 # Finelly, if we create more than one free square with a
1413 # single exit, we can only move to one of them next, leaving
1414 # the other one a dead end.
1415 ne0 = ne1 = 0
1416 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001417 s = succs[i]
1418 s.remove(i0)
1419 e = len(s)
1420 if e == 0:
1421 ne0 += 1
1422 elif e == 1:
1423 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001424 return ne0 == 0 and ne1 < 2
1425
Tim Peters9a8c8e22001-07-13 09:12:12 +00001426 # Put i0 back in each of its successor's successor lists.
1427
1428 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001429 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001430 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001431
1432 # Generate the first move.
1433 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001434 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001435 return
1436
unknown31569562001-07-04 22:11:22 +00001437 # Since we're looking for a cycle, it doesn't matter where we
1438 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001439 corner = self.coords2index(0, 0)
1440 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001441 self.lastij = corner
1442 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001443 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001444
1445 # Generate the second moves.
1446 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001447 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001448 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001449 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001450 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001451 assert len(succs[corner]) == 2
1452 assert self.coords2index(1, 2) in succs[corner]
1453 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001454 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001455 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001456 # to (0, 0). Save its index in self.final so that moves before
1457 # the last know it must be kept free.
1458 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001459 this = self.coords2index(i, j)
1460 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001461 self.final = final
unknown31569562001-07-04 22:11:22 +00001462
Tim Peters9a8c8e22001-07-13 09:12:12 +00001463 remove_from_successors(this)
1464 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001465 self.lastij = this
1466 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001467 succs[final].remove(corner)
1468 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001469
Tim Peters9a8c8e22001-07-13 09:12:12 +00001470 # Generate moves 3 thru m*n-1.
1471 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001472 # If some successor has only one exit, must take it.
1473 # Else favor successors with fewer exits.
1474 candidates = []
1475 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001476 e = len(succs[i])
1477 assert e > 0, "else remove_from_successors() pruning flawed"
1478 if e == 1:
1479 candidates = [(e, i)]
1480 break
1481 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001482 else:
1483 candidates.sort()
1484
1485 for e, i in candidates:
1486 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001487 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001488 self.lastij = i
1489 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001490 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001491
Tim Peters9a8c8e22001-07-13 09:12:12 +00001492 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001493 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001494 # Since the # of backtracking levels is m*n, a poor move early on
1495 # can take eons to undo. Smallest square board for which this
1496 # matters a lot is 52x52.
1497 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001498 # If some successor has only one exit, must take it.
1499 # Else favor successors with fewer exits.
1500 # Break ties via max distance from board centerpoint (favor
1501 # corners and edges whenever possible).
1502 candidates = []
1503 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001504 e = len(succs[i])
1505 assert e > 0, "else remove_from_successors() pruning flawed"
1506 if e == 1:
1507 candidates = [(e, 0, i)]
1508 break
1509 i1, j1 = self.index2coords(i)
1510 d = (i1 - vmid)**2 + (j1 - hmid)**2
1511 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001512 else:
1513 candidates.sort()
1514
1515 for e, d, i in candidates:
1516 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001517 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001518 self.lastij = i
1519 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001520 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001521
1522 # Generate the last move.
1523 def last():
1524 assert self.final in succs[self.lastij]
1525 yield self.final
1526
Tim Peters9a8c8e22001-07-13 09:12:12 +00001527 if m*n < 4:
1528 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001529 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001530 self.squaregenerators = [first, second] + \
1531 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001532 [last]
1533
Tim Peters9a8c8e22001-07-13 09:12:12 +00001534 def coords2index(self, i, j):
1535 assert 0 <= i < self.m
1536 assert 0 <= j < self.n
1537 return i * self.n + j
1538
1539 def index2coords(self, index):
1540 assert 0 <= index < self.m * self.n
1541 return divmod(index, self.n)
1542
1543 def _init_board(self):
1544 succs = self.succs
1545 del succs[:]
1546 m, n = self.m, self.n
1547 c2i = self.coords2index
1548
1549 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1550 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1551 rangen = range(n)
1552 for i in range(m):
1553 for j in rangen:
1554 s = [c2i(i+io, j+jo) for io, jo in offsets
1555 if 0 <= i+io < m and
1556 0 <= j+jo < n]
1557 succs.append(s)
1558
unknown31569562001-07-04 22:11:22 +00001559 # Generate solutions.
1560 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001561 self._init_board()
1562 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001563 yield x
1564
1565 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001566 m, n = self.m, self.n
1567 assert len(x) == m*n
1568 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001569 format = "%" + str(w) + "d"
1570
Tim Peters9a8c8e22001-07-13 09:12:12 +00001571 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001572 k = 1
1573 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001574 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001575 squares[i1][j1] = format % k
1576 k += 1
1577
1578 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001579 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001580 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001581 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001582 print("|" + "|".join(row) + "|")
1583 print(sep)
unknown31569562001-07-04 22:11:22 +00001584
Tim Petersbe4f0a72001-06-29 02:41:16 +00001585conjoin_tests = """
1586
1587Generate the 3-bit binary numbers in order. This illustrates dumbest-
1588possible use of conjoin, just to generate the full cross-product.
1589
unknown31569562001-07-04 22:11:22 +00001590>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001591... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001592[0, 0, 0]
1593[0, 0, 1]
1594[0, 1, 0]
1595[0, 1, 1]
1596[1, 0, 0]
1597[1, 0, 1]
1598[1, 1, 0]
1599[1, 1, 1]
1600
Tim Petersc468fd22001-06-30 07:29:44 +00001601For efficiency in typical backtracking apps, conjoin() yields the same list
1602object each time. So if you want to save away a full account of its
1603generated sequence, you need to copy its results.
1604
1605>>> def gencopy(iterator):
1606... for x in iterator:
1607... yield x[:]
1608
1609>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001610... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001611... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000016120 1 True True
16131 2 True True
16142 4 True True
16153 8 True True
16164 16 True True
16175 32 True True
16186 64 True True
16197 128 True True
16208 256 True True
16219 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001622
Tim Petersbe4f0a72001-06-29 02:41:16 +00001623And run an 8-queens solver.
1624
1625>>> q = Queens(8)
1626>>> LIMIT = 2
1627>>> count = 0
1628>>> for row2col in q.solve():
1629... count += 1
1630... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001631... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001632... q.printsolution(row2col)
1633Solution 1
1634+-+-+-+-+-+-+-+-+
1635|Q| | | | | | | |
1636+-+-+-+-+-+-+-+-+
1637| | | | |Q| | | |
1638+-+-+-+-+-+-+-+-+
1639| | | | | | | |Q|
1640+-+-+-+-+-+-+-+-+
1641| | | | | |Q| | |
1642+-+-+-+-+-+-+-+-+
1643| | |Q| | | | | |
1644+-+-+-+-+-+-+-+-+
1645| | | | | | |Q| |
1646+-+-+-+-+-+-+-+-+
1647| |Q| | | | | | |
1648+-+-+-+-+-+-+-+-+
1649| | | |Q| | | | |
1650+-+-+-+-+-+-+-+-+
1651Solution 2
1652+-+-+-+-+-+-+-+-+
1653|Q| | | | | | | |
1654+-+-+-+-+-+-+-+-+
1655| | | | | |Q| | |
1656+-+-+-+-+-+-+-+-+
1657| | | | | | | |Q|
1658+-+-+-+-+-+-+-+-+
1659| | |Q| | | | | |
1660+-+-+-+-+-+-+-+-+
1661| | | | | | |Q| |
1662+-+-+-+-+-+-+-+-+
1663| | | |Q| | | | |
1664+-+-+-+-+-+-+-+-+
1665| |Q| | | | | | |
1666+-+-+-+-+-+-+-+-+
1667| | | | |Q| | | |
1668+-+-+-+-+-+-+-+-+
1669
Guido van Rossum7131f842007-02-09 20:13:25 +00001670>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000167192 solutions in all.
unknown31569562001-07-04 22:11:22 +00001672
1673And run a Knight's Tour on a 10x10 board. Note that there are about
167420,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1675
Tim Peters9a8c8e22001-07-13 09:12:12 +00001676>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001677>>> LIMIT = 2
1678>>> count = 0
1679>>> for x in k.solve():
1680... count += 1
1681... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001682... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001683... k.printsolution(x)
1684... else:
1685... break
1686Solution 1
1687+---+---+---+---+---+---+---+---+---+---+
1688| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1689+---+---+---+---+---+---+---+---+---+---+
1690| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1691+---+---+---+---+---+---+---+---+---+---+
1692| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1693+---+---+---+---+---+---+---+---+---+---+
1694| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1695+---+---+---+---+---+---+---+---+---+---+
1696| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1697+---+---+---+---+---+---+---+---+---+---+
1698| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1699+---+---+---+---+---+---+---+---+---+---+
1700| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1701+---+---+---+---+---+---+---+---+---+---+
1702| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1703+---+---+---+---+---+---+---+---+---+---+
1704| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1705+---+---+---+---+---+---+---+---+---+---+
1706| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1707+---+---+---+---+---+---+---+---+---+---+
1708Solution 2
1709+---+---+---+---+---+---+---+---+---+---+
1710| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1711+---+---+---+---+---+---+---+---+---+---+
1712| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1713+---+---+---+---+---+---+---+---+---+---+
1714| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1715+---+---+---+---+---+---+---+---+---+---+
1716| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1717+---+---+---+---+---+---+---+---+---+---+
1718| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1719+---+---+---+---+---+---+---+---+---+---+
1720| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1721+---+---+---+---+---+---+---+---+---+---+
1722| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1723+---+---+---+---+---+---+---+---+---+---+
1724| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1725+---+---+---+---+---+---+---+---+---+---+
1726| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1727+---+---+---+---+---+---+---+---+---+---+
1728| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1729+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001730"""
1731
Fred Drake56d12662002-08-09 18:37:10 +00001732weakref_tests = """\
1733Generators are weakly referencable:
1734
1735>>> import weakref
1736>>> def gen():
1737... yield 'foo!'
1738...
1739>>> wr = weakref.ref(gen)
1740>>> wr() is gen
1741True
1742>>> p = weakref.proxy(gen)
1743
1744Generator-iterators are weakly referencable as well:
1745
1746>>> gi = gen()
1747>>> wr = weakref.ref(gi)
1748>>> wr() is gi
1749True
1750>>> p = weakref.proxy(gi)
1751>>> list(p)
1752['foo!']
1753
1754"""
1755
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001756coroutine_tests = """\
1757Sending a value into a started generator:
1758
1759>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001760... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001761... yield 2
1762>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001763>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000017641
1765>>> g.send(42)
176642
17672
1768
1769Sending a value into a new generator produces a TypeError:
1770
1771>>> f().send("foo")
1772Traceback (most recent call last):
1773...
1774TypeError: can't send non-None value to a just-started generator
1775
1776
1777Yield by itself yields None:
1778
1779>>> def f(): yield
1780>>> list(f())
1781[None]
1782
1783
1784
1785An obscene abuse of a yield expression within a generator expression:
1786
1787>>> list((yield 21) for i in range(4))
1788[21, None, 21, None, 21, None, 21, None]
1789
1790And a more sane, but still weird usage:
1791
1792>>> def f(): list(i for i in [(yield 26)])
1793>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00001794<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001795
1796
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001797A yield expression with augmented assignment.
1798
1799>>> def coroutine(seq):
1800... count = 0
1801... while count < 200:
1802... count += yield
1803... seq.append(count)
1804>>> seq = []
1805>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001806>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001807>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001808[]
1809>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001810>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001811[10]
1812>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001813>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001814[10, 20]
1815>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001816>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001817[10, 20, 30]
1818
1819
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001820Check some syntax errors for yield expressions:
1821
1822>>> f=lambda: (yield 1),(yield 2)
1823Traceback (most recent call last):
1824 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001825SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001826
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001827>>> def f(): x = yield = y
1828Traceback (most recent call last):
1829 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001830SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001831
1832>>> def f(): (yield bar) = y
1833Traceback (most recent call last):
1834 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001835SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001836
1837>>> def f(): (yield bar) += y
1838Traceback (most recent call last):
1839 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001840SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001841
1842
1843Now check some throw() conditions:
1844
1845>>> def f():
1846... while True:
1847... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001848... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001849... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001850... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001851>>> import sys
1852>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001853>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001854
1855>>> g.throw(ValueError) # type only
1856caught ValueError ()
1857
1858>>> g.throw(ValueError("xyz")) # value only
1859caught ValueError (xyz)
1860
1861>>> g.throw(ValueError, ValueError(1)) # value+matching type
1862caught ValueError (1)
1863
1864>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1865caught ValueError (1)
1866
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001867>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1868caught ValueError (1)
1869
Tim Peterse9fe7e02005-08-07 03:04:58 +00001870>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001871Traceback (most recent call last):
1872 ...
1873TypeError: instance exception may not have a separate value
1874
Tim Peterse9fe7e02005-08-07 03:04:58 +00001875>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001876Traceback (most recent call last):
1877 ...
1878TypeError: throw() third argument must be a traceback object
1879
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001880>>> g.throw("abc")
1881Traceback (most recent call last):
1882 ...
1883TypeError: exceptions must be classes or instances deriving from BaseException, not str
1884
1885>>> g.throw(0)
1886Traceback (most recent call last):
1887 ...
1888TypeError: exceptions must be classes or instances deriving from BaseException, not int
1889
1890>>> g.throw(list)
1891Traceback (most recent call last):
1892 ...
1893TypeError: exceptions must be classes or instances deriving from BaseException, not type
1894
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001895>>> def throw(g,exc):
1896... try:
1897... raise exc
1898... except:
1899... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001900>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001901caught ValueError ()
1902
1903>>> g.send(1)
19041
1905
Tim Peterse9fe7e02005-08-07 03:04:58 +00001906>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001907Traceback (most recent call last):
1908 ...
1909TypeError
1910
Guido van Rossum7131f842007-02-09 20:13:25 +00001911>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001912None
1913
1914>>> g.send(2)
1915Traceback (most recent call last):
1916 ...
1917StopIteration
1918
Tim Peterse9fe7e02005-08-07 03:04:58 +00001919>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001920Traceback (most recent call last):
1921 ...
1922ValueError: 6
1923
Tim Peterse9fe7e02005-08-07 03:04:58 +00001924>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001925Traceback (most recent call last):
1926 ...
1927ValueError: 7
1928
Antoine Pitrou551ba202011-10-18 16:40:50 +02001929Plain "raise" inside a generator should preserve the traceback (#13188).
1930The traceback should have 3 levels:
1931- g.throw()
1932- f()
1933- 1/0
1934
1935>>> def f():
1936... try:
1937... yield
1938... except:
1939... raise
1940>>> g = f()
1941>>> try:
1942... 1/0
1943... except ZeroDivisionError as v:
1944... try:
1945... g.throw(v)
1946... except Exception as w:
1947... tb = w.__traceback__
1948>>> levels = 0
1949>>> while tb:
1950... levels += 1
1951... tb = tb.tb_next
1952>>> levels
19533
1954
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001955Now let's try closing a generator:
1956
1957>>> def f():
1958... try: yield
1959... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00001960... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001961
1962>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001963>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001964>>> g.close()
1965exiting
1966>>> g.close() # should be no-op now
1967
1968>>> f().close() # close on just-opened generator should be fine
1969
Tim Peterse9fe7e02005-08-07 03:04:58 +00001970>>> def f(): yield # an even simpler generator
1971>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001972>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001973>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00001974>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001975
1976And finalization:
1977
1978>>> def f():
1979... try: yield
1980... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00001981... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001982
1983>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001984>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001985>>> del g
1986exiting
1987
1988
Christian Heimescbf3b5c2007-12-03 21:02:03 +00001989GeneratorExit is not caught by except Exception:
1990
1991>>> def f():
1992... try: yield
1993... except Exception:
1994... print('except')
1995... finally:
1996... print('finally')
1997
1998>>> g = f()
1999>>> next(g)
2000>>> del g
2001finally
2002
2003
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002004Now let's try some ill-behaved generators:
2005
2006>>> def f():
2007... try: yield
2008... except GeneratorExit:
2009... yield "foo!"
2010>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002011>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002012>>> g.close()
2013Traceback (most recent call last):
2014 ...
2015RuntimeError: generator ignored GeneratorExit
2016>>> g.close()
2017
2018
2019Our ill-behaved code should be invoked during GC:
2020
Guido van Rossum34d19282007-08-09 01:03:29 +00002021>>> import sys, io
2022>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002023>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002024>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002025>>> del g
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002026>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002027True
2028>>> sys.stderr = old
2029
2030
2031And errors thrown during closing should propagate:
2032
2033>>> def f():
2034... try: yield
2035... except GeneratorExit:
2036... raise TypeError("fie!")
2037>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002038>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002039>>> g.close()
2040Traceback (most recent call last):
2041 ...
2042TypeError: fie!
2043
2044
2045Ensure that various yield expression constructs make their
2046enclosing function a generator:
2047
2048>>> def f(): x += yield
2049>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00002050<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002051
2052>>> def f(): x = yield
2053>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00002054<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002055
2056>>> def f(): lambda x=(yield): 1
2057>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00002058<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002059
2060>>> def f(): x=(i for i in (yield) if (yield))
2061>>> type(f())
Martin v. Löwis250ad612008-04-07 05:43:42 +00002062<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002063
2064>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
2065>>> data = [1,2]
2066>>> g = f(data)
2067>>> type(g)
Martin v. Löwis250ad612008-04-07 05:43:42 +00002068<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002069>>> g.send(None)
2070'a'
2071>>> data
2072[1, 2]
2073>>> g.send(0)
2074'b'
2075>>> data
2076[27, 2]
2077>>> try: g.send(1)
2078... except StopIteration: pass
2079>>> data
2080[27, 27]
2081
2082"""
2083
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002084refleaks_tests = """
2085Prior to adding cycle-GC support to itertools.tee, this code would leak
2086references. We add it to the standard suite so the routine refleak-tests
2087would trigger if it starts being uncleanable again.
2088
2089>>> import itertools
2090>>> def leak():
2091... class gen:
2092... def __iter__(self):
2093... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002094... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002095... return self.item
2096... g = gen()
2097... head, tail = itertools.tee(g)
2098... g.item = head
2099... return head
2100>>> it = leak()
2101
2102Make sure to also test the involvement of the tee-internal teedataobject,
2103which stores returned items.
2104
Georg Brandla18af4e2007-04-21 15:47:16 +00002105>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002106
2107
2108
2109This test leaked at one point due to generator finalization/destruction.
2110It was copied from Lib/test/leakers/test_generator_cycle.py before the file
2111was removed.
2112
2113>>> def leak():
2114... def gen():
2115... while True:
2116... yield g
2117... g = gen()
2118
2119>>> leak()
2120
2121
2122
2123This test isn't really generator related, but rather exception-in-cleanup
2124related. The coroutine tests (above) just happen to cause an exception in
2125the generator's __del__ (tp_del) method. We can also test for this
2126explicitly, without generators. We do have to redirect stderr to avoid
2127printing warnings and to doublecheck that we actually tested what we wanted
2128to test.
2129
Guido van Rossum34d19282007-08-09 01:03:29 +00002130>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002131>>> old = sys.stderr
2132>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00002133... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002134... class Leaker:
2135... def __del__(self):
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002136... def invoke(message):
2137... raise RuntimeError(message)
2138... invoke("test")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002139...
2140... l = Leaker()
2141... del l
2142... err = sys.stderr.getvalue().strip()
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002143... "Exception ignored in" in err
2144... "RuntimeError: test" in err
2145... "Traceback" in err
2146... "in invoke" in err
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002147... finally:
2148... sys.stderr = old
2149True
2150True
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002151True
2152True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002153
2154
2155These refleak tests should perhaps be in a testfile of their own,
2156test_generators just happened to be the test that drew these out.
2157
2158"""
2159
Tim Petersf6ed0742001-06-27 07:17:57 +00002160__test__ = {"tut": tutorial_tests,
2161 "pep": pep_tests,
2162 "email": email_tests,
2163 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00002164 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00002165 "conjoin": conjoin_tests,
2166 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002167 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002168 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00002169 }
Tim Peters1def3512001-06-23 20:27:04 +00002170
2171# Magic test name that regrtest.py invokes *after* importing this module.
2172# This worms around a bootstrap problem.
2173# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
2174# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00002175def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002176 from test import support, test_generators
Antoine Pitrou796564c2013-07-30 19:59:21 +02002177 support.run_unittest(__name__)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002178 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00002179
2180# This part isn't needed for regrtest, but for running the test directly.
2181if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00002182 test_main(1)