2
Let's try a simple generator:
18
"Falling off the end" stops the generator:
21
Traceback (most recent call last):
22
File "<stdin>", line 1, in ?
23
File "<stdin>", line 2, in g
26
"return" also stops the generator:
31
... yield 2 # never reached
37
Traceback (most recent call last):
38
File "<stdin>", line 1, in ?
39
File "<stdin>", line 3, in f
41
>>> g.next() # once stopped, can't be resumed
42
Traceback (most recent call last):
43
File "<stdin>", line 1, in ?
46
"raise StopIteration" stops the generator too:
50
... raise StopIteration
51
... yield 2 # never reached
57
Traceback (most recent call last):
58
File "<stdin>", line 1, in ?
61
Traceback (most recent call last):
62
File "<stdin>", line 1, in ?
65
However, they are not exactly equivalent:
78
... raise StopIteration
84
This may be surprising at first:
95
Let's create an alternate range() function implemented as a generator:
98
... for i in range(n):
104
Generators always return to the most recent caller:
108
... print "creator", r.next()
114
... print "caller", i
123
Generators can call other generators:
126
... for i in yrange(n):
134
# The examples from PEP 255.
140
Restriction: A generator cannot be resumed while it is actively
148
Traceback (most recent call last):
150
File "<string>", line 2, in g
151
ValueError: generator already executing
153
Specification: Return
155
Note that return isn't always equivalent to raising StopIteration: the
156
difference lies in how enclosing try/except constructs are treated.
167
because, as in any function, return simply exits, but
171
... raise StopIteration
177
because StopIteration is captured by a bare "except", as is any
180
Specification: Generators and Exception Propagation
185
... yield f() # the zero division exception propagates
186
... yield 42 # and we'll never get here
189
Traceback (most recent call last):
190
File "<stdin>", line 1, in ?
191
File "<stdin>", line 2, in g
192
File "<stdin>", line 2, in f
193
ZeroDivisionError: integer division or modulo by zero
194
>>> k.next() # and the generator cannot be resumed
195
Traceback (most recent call last):
196
File "<stdin>", line 1, in ?
200
Specification: Try/Except/Finally
208
... yield 3 # never get here
209
... except ZeroDivisionError:
215
... yield 7 # the "raise" above stops this
225
[1, 2, 4, 5, 8, 9, 10, 11]
228
Guido's binary tree example.
230
>>> # A binary tree class.
233
... def __init__(self, label, left=None, right=None):
234
... self.label = label
236
... self.right = right
238
... def __repr__(self, level=0, indent=" "):
239
... s = level*indent + repr(self.label)
241
... s = s + "\\n" + self.left.__repr__(level+1, indent)
243
... s = s + "\\n" + self.right.__repr__(level+1, indent)
246
... def __iter__(self):
247
... return inorder(self)
249
>>> # Create a Tree from a list.
255
... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
257
>>> # Show it off: create a tree.
258
>>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
260
>>> # A recursive generator that generates Tree labels in in-order.
263
... for x in inorder(t.left):
266
... for x in inorder(t.right):
269
>>> # Show it off: create a tree.
270
>>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
271
>>> # Print the nodes of the tree in in-order.
274
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
276
>>> # A non-recursive generator.
277
>>> def inorder(node):
281
... stack.append(node)
284
... while not node.right:
286
... node = stack.pop()
287
... except IndexError:
290
... node = node.right
292
>>> # Exercise the non-recursive generator.
295
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
299
# Examples from Iterator-List and Python-Dev and c.l.py.
303
The difference between yielding None and returning it.
306
... for i in range(3):
311
[None, None, None, None]
313
Ensure that explicitly raising StopIteration acts like any other exception
314
in try/except, not like a return.
319
... raise StopIteration
326
Next one was posted to c.l.py.
329
... "Generate all combinations of k elements from list x."
336
... first, rest = x[0], x[1:]
337
... # A combination does or doesn't contain first.
338
... # If it does, the remainder is a k-1 comb of rest.
339
... for c in gcomb(rest, k-1):
340
... c.insert(0, first)
342
... # If it doesn't contain first, it's a k comb of rest.
343
... for c in gcomb(rest, k):
346
>>> seq = range(1, 5)
347
>>> for k in range(len(seq) + 2):
348
... print "%d-combs of %s:" % (k, seq)
349
... for c in gcomb(seq, k):
351
0-combs of [1, 2, 3, 4]:
353
1-combs of [1, 2, 3, 4]:
358
2-combs of [1, 2, 3, 4]:
365
3-combs of [1, 2, 3, 4]:
370
4-combs of [1, 2, 3, 4]:
372
5-combs of [1, 2, 3, 4]:
374
From the Iterators list, about the types of these things.
384
>>> [s for s in dir(i) if not s.startswith('_')]
385
['gi_frame', 'gi_running', 'next']
386
>>> print i.next.__doc__
387
x.next() -> the next value, or raise StopIteration
391
>>> isinstance(i, types.GeneratorType)
394
And more, added later.
400
>>> i.gi_running = 42
401
Traceback (most recent call last):
403
TypeError: readonly attribute
405
... yield me.gi_running
414
A clever union-find implementation from c.l.py, due to David Eppstein.
415
Sent: Friday, June 29, 2001 12:16 PM
416
To: python-list@python.org
417
Subject: Re: PEP 255: Simple Generators
419
>>> class disjointSet:
420
... def __init__(self, name):
422
... self.parent = None
423
... self.generator = self.generate()
425
... def generate(self):
426
... while not self.parent:
428
... for x in self.parent.generator:
432
... return self.generator.next()
434
... def union(self, parent):
436
... raise ValueError("Sorry, I'm not a root!")
437
... self.parent = parent
439
... def __str__(self):
442
>>> names = "ABCDEFGHIJKLM"
443
>>> sets = [disjointSet(name) for name in names]
447
>>> gen = random.WichmannHill(42)
450
... print "%s->%s" % (s, s.find()),
452
... if len(roots) > 1:
453
... s1 = gen.choice(roots)
455
... s2 = gen.choice(roots)
457
... print "merged", s1, "into", s2
460
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
462
A->A B->B C->C D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
464
A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
466
A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->A M->M
468
A->A B->B C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
470
A->A B->E C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
472
A->A B->E C->F D->G E->E F->F G->G H->E I->I J->G K->K L->A M->M
474
A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->M
476
A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->G
478
A->A B->G C->F D->G E->G F->F G->G H->G I->K J->G K->K L->A M->G
480
A->A B->G C->F D->G E->G F->F G->G H->G I->A J->G K->A L->A M->G
482
A->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G
484
A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G
488
# Fun tests (for sufficiently warped notions of "fun").
492
Build up to a recursive Sieve of Eratosthenes generator.
494
>>> def firstn(g, n):
495
... return [g.next() for i in range(n)]
502
>>> firstn(intsfrom(5), 7)
503
[5, 6, 7, 8, 9, 10, 11]
505
>>> def exclude_multiples(n, ints):
510
>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
514
... prime = ints.next()
516
... not_divisible_by_prime = exclude_multiples(prime, ints)
517
... for p in sieve(not_divisible_by_prime):
520
>>> primes = sieve(intsfrom(2))
521
>>> firstn(primes, 20)
522
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
525
Another famous problem: generate all integers of the form
527
in increasing order, where i,j,k >= 0. Trickier than it may look at first!
528
Try writing it without generators, and correctly, and without generating
529
3 internal results for each result output.
534
>>> firstn(times(10, intsfrom(1)), 10)
535
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
552
The following works, but is doing a whale of a lot of redundant work --
553
it's not clear how to get the internal uses of m235 to share a single
554
generator. Note that me_times2 (etc) each need to see every element in the
555
result sequence. So this is an example where lazy lists are more natural
556
(you can look at the head of a lazy list any number of times).
560
... me_times2 = times(2, m235())
561
... me_times3 = times(3, m235())
562
... me_times5 = times(5, m235())
563
... for i in merge(merge(me_times2,
568
Don't print "too many" of these -- the implementation above is extremely
569
inefficient: each call of m235() leads to 3 recursive calls, and in
570
turn each of those 3 more, and so on, and so on, until we've descended
571
enough levels to satisfy the print stmts. Very odd: when I printed 5
572
lines of results below, this managed to screw up Win98's malloc in "the
573
usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
574
address space, and it *looked* like a very slow leak.
577
>>> for i in range(3):
578
... print firstn(result, 15)
579
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
580
[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
581
[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
583
Heh. Here's one way to get a shared list, complete with an excruciating
584
namespace renaming trick. The *pretty* part is that the times() and merge()
585
functions can be reused as-is, because they only assume their stream
586
arguments are iterable -- a LazyList is the same as a generator to times().
589
... def __init__(self, g):
591
... self.fetch = g.next
593
... def __getitem__(self, i):
594
... sofar, fetch = self.sofar, self.fetch
595
... while i >= len(sofar):
596
... sofar.append(fetch())
601
... # Gack: m235 below actually refers to a LazyList.
602
... me_times2 = times(2, m235)
603
... me_times3 = times(3, m235)
604
... me_times5 = times(5, m235)
605
... for i in merge(merge(me_times2,
610
Print as many of these as you like -- *this* implementation is memory-
613
>>> m235 = LazyList(m235())
614
>>> for i in range(5):
615
... print [m235[j] for j in range(15*i, 15*(i+1))]
616
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
617
[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
618
[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
619
[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
620
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
623
Ye olde Fibonacci generator, LazyList style.
625
>>> def fibgen(a, b):
629
... yield g.next() + h.next()
632
... g.next() # throw first away
638
... for s in sum(iter(fib),
639
... tail(iter(fib))):
642
>>> fib = LazyList(fibgen(1, 2))
643
>>> firstn(iter(fib), 17)
644
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
647
# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
655
Traceback (most recent call last):
657
SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2)
662
Traceback (most recent call last):
664
SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)
666
"return None" is not the same as "return" in a generator:
671
Traceback (most recent call last):
673
SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
686
Traceback (most recent call last):
688
SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[4]>, line 3)
694
... except ZeroDivisionError:
695
... yield 666 # bad because *outer* try has finally
700
Traceback (most recent call last):
702
SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[5]>, line 6)
711
... except ZeroDivisionError:
725
Traceback (most recent call last):
726
SyntaxError: invalid syntax
731
Traceback (most recent call last):
732
SyntaxError: invalid syntax
754
... except SyntaxError:
760
... yield 2 # don't blink
781
... def __init__(self):
799
... lambda x: x # shouldn't trigger here
802
... return 2*i # or here
804
... return 3 # but *this* sucks (line 8)
806
... yield 2 # because it's a generator
807
Traceback (most recent call last):
808
SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[22]>, line 8)
810
This one caused a crash (see SF bug 567538):
813
... for i in range(3):
827
Traceback (most recent call last):
831
# conjoin is a simple backtracking generator, named in honor of Icon's
832
# "conjunction" control structure. Pass a list of no-argument functions
833
# that return iterable objects. Easiest to explain by example: assume the
834
# function list [x, y, z] is passed. Then conjoin acts like:
837
# values = [None] * 3
838
# for values[0] in x():
839
# for values[1] in y():
840
# for values[2] in z():
843
# So some 3-lists of values *may* be generated, each time we successfully
844
# get into the innermost loop. If an iterator fails (is exhausted) before
845
# then, it "backtracks" to get the next value from the nearest enclosing
846
# iterator (the one "to the left"), and starts all over again at the next
847
# slot (pumps a fresh iterator). Of course this is most useful when the
848
# iterators have side-effects, so that which values *can* be generated at
849
# each slot depend on the values iterated at previous slots.
853
values = [None] * len(gs)
855
def gen(i, values=values):
859
for values[i] in gs[i]():
866
# That works fine, but recursing a level and checking i against len(gs) for
867
# each item produced is inefficient. By doing manual loop unrolling across
868
# generator boundaries, it's possible to eliminate most of that overhead.
869
# This isn't worth the bother *in general* for generators, but conjoin() is
870
# a core building block for some CPU-intensive generator applications.
877
# Do one loop nest at time recursively, until the # of loop nests
878
# remaining is divisible by 3.
880
def gen(i, values=values):
886
for values[i] in gs[i]():
894
# Do three loop nests at a time, recursing only if at least three more
895
# remain. Don't call directly: this is an internal optimization for
898
def _gen3(i, values=values):
899
assert i < n and (n-i) % 3 == 0
900
ip1, ip2, ip3 = i+1, i+2, i+3
901
g, g1, g2 = gs[i : ip3]
904
# These are the last three, so we can yield values directly.
905
for values[i] in g():
906
for values[ip1] in g1():
907
for values[ip2] in g2():
911
# At least 6 loop nests remain; peel off 3 and recurse for the
913
for values[i] in g():
914
for values[ip1] in g1():
915
for values[ip2] in g2():
922
# And one more approach: For backtracking apps like the Knight's Tour
923
# solver below, the number of backtracking levels can be enormous (one
924
# level per square, for the Knight's Tour, so that e.g. a 100x100 board
925
# needs 10,000 levels). In such cases Python is likely to run out of
926
# stack space due to recursion. So here's a recursion-free version of
928
# NOTE WELL: This allows large problems to be solved with only trivial
929
# demands on stack space. Without explicitly resumable generators, this is
930
# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
931
# than the fancy unrolled recursive conjoin.
933
def flat_conjoin(gs): # rename to conjoin to run tests with this instead
937
_StopIteration = StopIteration # make local because caught a *lot*
943
it = iters[i] = gs[i]().next
946
except _StopIteration:
952
# Backtrack until an older iterator can be resumed.
956
values[i] = iters[i]()
957
# Success! Start fresh at next level.
960
except _StopIteration:
961
# Continue backtracking.
967
# A conjoin-based N-Queens solver.
970
def __init__(self, n):
974
# Assign a unique int to each column and diagonal.
975
# columns: n of those, range(n).
976
# NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
977
# each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
979
# NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
980
# each, smallest i+j is 0, largest is 2n-2.
982
# For each square, compute a bit vector of the columns and
983
# diagonals it covers, and for each row compute a function that
984
# generates the possiblities for the columns in that row.
985
self.rowgenerators = []
987
rowuses = [(1L << j) | # column ordinal
988
(1L << (n + i-j + n-1)) | # NW-SE ordinal
989
(1L << (n + 2*n-1 + i+j)) # NE-SW ordinal
992
def rowgen(rowuses=rowuses):
995
if uses & self.used == 0:
1000
self.rowgenerators.append(rowgen)
1002
# Generate solutions.
1005
for row2col in conjoin(self.rowgenerators):
1008
def printsolution(self, row2col):
1010
assert n == len(row2col)
1011
sep = "+" + "-+" * n
1014
squares = [" " for j in range(n)]
1015
squares[row2col[i]] = "Q"
1016
print "|" + "|".join(squares) + "|"
1019
# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1020
# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1021
# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
1022
# creating 10s of thousands of generators then!), and is lengthy.
1025
def __init__(self, m, n, hard=0):
1026
self.m, self.n = m, n
1028
# solve() will set up succs[i] to be a list of square #i's
1030
succs = self.succs = []
1032
# Remove i0 from each of its successor's successor lists, i.e.
1033
# successors can't go back to i0 again. Return 0 if we can
1034
# detect this makes a solution impossible, else return 1.
1036
def remove_from_successors(i0, len=len):
1037
# If we remove all exits from a free square, we're dead:
1038
# even if we move to it next, we can't leave it again.
1039
# If we create a square with one exit, we must visit it next;
1040
# else somebody else will have to visit it, and since there's
1041
# only one adjacent, there won't be a way to leave it again.
1042
# Finelly, if we create more than one free square with a
1043
# single exit, we can only move to one of them next, leaving
1044
# the other one a dead end.
1054
return ne0 == 0 and ne1 < 2
1056
# Put i0 back in each of its successor's successor lists.
1058
def add_to_successors(i0):
1062
# Generate the first move.
1067
# Since we're looking for a cycle, it doesn't matter where we
1068
# start. Starting in a corner makes the 2nd move easy.
1069
corner = self.coords2index(0, 0)
1070
remove_from_successors(corner)
1071
self.lastij = corner
1073
add_to_successors(corner)
1075
# Generate the second moves.
1077
corner = self.coords2index(0, 0)
1078
assert self.lastij == corner # i.e., we started in the corner
1081
assert len(succs[corner]) == 2
1082
assert self.coords2index(1, 2) in succs[corner]
1083
assert self.coords2index(2, 1) in succs[corner]
1084
# Only two choices. Whichever we pick, the other must be the
1085
# square picked on move m*n, as it's the only way to get back
1086
# to (0, 0). Save its index in self.final so that moves before
1087
# the last know it must be kept free.
1088
for i, j in (1, 2), (2, 1):
1089
this = self.coords2index(i, j)
1090
final = self.coords2index(3-i, 3-j)
1093
remove_from_successors(this)
1094
succs[final].append(corner)
1097
succs[final].remove(corner)
1098
add_to_successors(this)
1100
# Generate moves 3 thru m*n-1.
1101
def advance(len=len):
1102
# If some successor has only one exit, must take it.
1103
# Else favor successors with fewer exits.
1105
for i in succs[self.lastij]:
1107
assert e > 0, "else remove_from_successors() pruning flawed"
1109
candidates = [(e, i)]
1111
candidates.append((e, i))
1115
for e, i in candidates:
1117
if remove_from_successors(i):
1120
add_to_successors(i)
1122
# Generate moves 3 thru m*n-1. Alternative version using a
1123
# stronger (but more expensive) heuristic to order successors.
1124
# Since the # of backtracking levels is m*n, a poor move early on
1125
# can take eons to undo. Smallest square board for which this
1126
# matters a lot is 52x52.
1127
def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
1128
# If some successor has only one exit, must take it.
1129
# Else favor successors with fewer exits.
1130
# Break ties via max distance from board centerpoint (favor
1131
# corners and edges whenever possible).
1133
for i in succs[self.lastij]:
1135
assert e > 0, "else remove_from_successors() pruning flawed"
1137
candidates = [(e, 0, i)]
1139
i1, j1 = self.index2coords(i)
1140
d = (i1 - vmid)**2 + (j1 - hmid)**2
1141
candidates.append((e, -d, i))
1145
for e, d, i in candidates:
1147
if remove_from_successors(i):
1150
add_to_successors(i)
1152
# Generate the last move.
1154
assert self.final in succs[self.lastij]
1158
self.squaregenerators = [first]
1160
self.squaregenerators = [first, second] + \
1161
[hard and advance_hard or advance] * (m*n - 3) + \
1164
def coords2index(self, i, j):
1165
assert 0 <= i < self.m
1166
assert 0 <= j < self.n
1167
return i * self.n + j
1169
def index2coords(self, index):
1170
assert 0 <= index < self.m * self.n
1171
return divmod(index, self.n)
1173
def _init_board(self):
1176
m, n = self.m, self.n
1177
c2i = self.coords2index
1179
offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1180
(-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1184
s = [c2i(i+io, j+jo) for io, jo in offsets
1185
if 0 <= i+io < m and
1189
# Generate solutions.
1192
for x in conjoin(self.squaregenerators):
1195
def printsolution(self, x):
1196
m, n = self.m, self.n
1197
assert len(x) == m*n
1199
format = "%" + str(w) + "d"
1201
squares = [[None] * n for i in range(m)]
1204
i1, j1 = self.index2coords(i)
1205
squares[i1][j1] = format % k
1208
sep = "+" + ("-" * w + "+") * n
1212
print "|" + "|".join(row) + "|"
1217
Generate the 3-bit binary numbers in order. This illustrates dumbest-
1218
possible use of conjoin, just to generate the full cross-product.
1220
>>> for c in conjoin([lambda: iter((0, 1))] * 3):
1231
For efficiency in typical backtracking apps, conjoin() yields the same list
1232
object each time. So if you want to save away a full account of its
1233
generated sequence, you need to copy its results.
1235
>>> def gencopy(iterator):
1236
... for x in iterator:
1239
>>> for n in range(10):
1240
... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
1241
... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n
1253
And run an 8-queens solver.
1258
>>> for row2col in q.solve():
1260
... if count <= LIMIT:
1261
... print "Solution", count
1262
... q.printsolution(row2col)
1300
>>> print count, "solutions in all."
1301
92 solutions in all.
1303
And run a Knight's Tour on a 10x10 board. Note that there are about
1304
20,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1306
>>> k = Knights(10, 10)
1309
>>> for x in k.solve():
1311
... if count <= LIMIT:
1312
... print "Solution", count
1313
... k.printsolution(x)
1317
+---+---+---+---+---+---+---+---+---+---+
1318
| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1319
+---+---+---+---+---+---+---+---+---+---+
1320
| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1321
+---+---+---+---+---+---+---+---+---+---+
1322
| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1323
+---+---+---+---+---+---+---+---+---+---+
1324
| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1325
+---+---+---+---+---+---+---+---+---+---+
1326
| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1327
+---+---+---+---+---+---+---+---+---+---+
1328
| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1329
+---+---+---+---+---+---+---+---+---+---+
1330
| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1331
+---+---+---+---+---+---+---+---+---+---+
1332
| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1333
+---+---+---+---+---+---+---+---+---+---+
1334
| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1335
+---+---+---+---+---+---+---+---+---+---+
1336
| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1337
+---+---+---+---+---+---+---+---+---+---+
1339
+---+---+---+---+---+---+---+---+---+---+
1340
| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1341
+---+---+---+---+---+---+---+---+---+---+
1342
| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1343
+---+---+---+---+---+---+---+---+---+---+
1344
| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1345
+---+---+---+---+---+---+---+---+---+---+
1346
| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1347
+---+---+---+---+---+---+---+---+---+---+
1348
| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1349
+---+---+---+---+---+---+---+---+---+---+
1350
| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1351
+---+---+---+---+---+---+---+---+---+---+
1352
| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1353
+---+---+---+---+---+---+---+---+---+---+
1354
| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1355
+---+---+---+---+---+---+---+---+---+---+
1356
| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1357
+---+---+---+---+---+---+---+---+---+---+
1358
| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1359
+---+---+---+---+---+---+---+---+---+---+
1362
weakref_tests = """\
1363
Generators are weakly referencable:
1369
>>> wr = weakref.ref(gen)
1372
>>> p = weakref.proxy(gen)
1374
Generator-iterators are weakly referencable as well:
1377
>>> wr = weakref.ref(gi)
1380
>>> p = weakref.proxy(gi)
1386
__test__ = {"tut": tutorial_tests,
1388
"email": email_tests,
1390
"syntax": syntax_tests,
1391
"conjoin": conjoin_tests,
1392
"weakref": weakref_tests,
1395
# Magic test name that regrtest.py invokes *after* importing this module.
1396
# This worms around a bootstrap problem.
1397
# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
1398
# so this works as expected in both ways of running regrtest.
1399
def test_main(verbose=None):
1400
from test import test_support, test_generators
1401
test_support.run_doctest(test_generators, verbose)
1403
# This part isn't needed for regrtest, but for running the test directly.
1404
if __name__ == "__main__":