Tryag File Manager
Home
-
Turbo Force
Current Path :
/
usr
/
lib
/
python2.4
/
test
/
Upload File :
New :
File
Dir
//usr/lib/python2.4/test/test_generators.pyc
mò ‚=5Dc�����������@���sÛ���d��Z��d�Z�d�Z�d�Z�d�Z�d�„��Z�d�„��Z�d�„��Z�d�f��d �„��ƒ��YZ�d �f��d�„��ƒ��YZ�d�Z �d �Z �h��d�e��<d�e�<d�e�<d�e�<d�e�<d�e �<d�e �<Z�d�d�„�Z �e�d�j�o�e �d�ƒ�n�d�S(���sÜ �� Let's try a simple generator: >>> def f(): ... yield 1 ... yield 2 >>> for i in f(): ... print i 1 2 >>> g = f() >>> g.next() 1 >>> g.next() 2 "Falling off the end" stops the generator: >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 2, in g StopIteration "return" also stops the generator: >>> def f(): ... yield 1 ... return ... yield 2 # never reached ... >>> g = f() >>> g.next() 1 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in f StopIteration >>> g.next() # once stopped, can't be resumed Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration "raise StopIteration" stops the generator too: >>> def f(): ... yield 1 ... raise StopIteration ... yield 2 # never reached ... >>> g = f() >>> g.next() 1 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration However, they are not exactly equivalent: >>> def g1(): ... try: ... return ... except: ... yield 1 ... >>> list(g1()) [] >>> def g2(): ... try: ... raise StopIteration ... except: ... yield 42 >>> print list(g2()) [42] This may be surprising at first: >>> def g3(): ... try: ... return ... finally: ... yield 1 ... >>> list(g3()) [1] Let's create an alternate range() function implemented as a generator: >>> def yrange(n): ... for i in range(n): ... yield i ... >>> list(yrange(5)) [0, 1, 2, 3, 4] Generators always return to the most recent caller: >>> def creator(): ... r = yrange(5) ... print "creator", r.next() ... return r ... >>> def caller(): ... r = creator() ... for i in r: ... print "caller", i ... >>> caller() creator 0 caller 1 caller 2 caller 3 caller 4 Generators can call other generators: >>> def zrange(n): ... for i in yrange(n): ... yield i ... >>> list(zrange(5)) [0, 1, 2, 3, 4] sq�� Specification: Yield Restriction: A generator cannot be resumed while it is actively running: >>> def g(): ... i = me.next() ... yield i >>> me = g() >>> me.next() Traceback (most recent call last): ... File "<string>", line 2, in g ValueError: generator already executing Specification: Return Note that return isn't always equivalent to raising StopIteration: the difference lies in how enclosing try/except constructs are treated. For example, >>> def f1(): ... try: ... return ... except: ... yield 1 >>> print list(f1()) [] because, as in any function, return simply exits, but >>> def f2(): ... try: ... raise StopIteration ... except: ... yield 42 >>> print list(f2()) [42] because StopIteration is captured by a bare "except", as is any exception. Specification: Generators and Exception Propagation >>> def f(): ... return 1//0 >>> def g(): ... yield f() # the zero division exception propagates ... yield 42 # and we'll never get here >>> k = g() >>> k.next() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 2, in g File "<stdin>", line 2, in f ZeroDivisionError: integer division or modulo by zero >>> k.next() # and the generator cannot be resumed Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration >>> Specification: Try/Except/Finally >>> def f(): ... try: ... yield 1 ... try: ... yield 2 ... 1//0 ... yield 3 # never get here ... except ZeroDivisionError: ... yield 4 ... yield 5 ... raise ... except: ... yield 6 ... yield 7 # the "raise" above stops this ... except: ... yield 8 ... yield 9 ... try: ... x = 12 ... finally: ... yield 10 ... yield 11 >>> print list(f()) [1, 2, 4, 5, 8, 9, 10, 11] >>> Guido's binary tree example. >>> # A binary tree class. >>> class Tree: ... ... def __init__(self, label, left=None, right=None): ... self.label = label ... self.left = left ... self.right = right ... ... def __repr__(self, level=0, indent=" "): ... s = level*indent + repr(self.label) ... if self.left: ... s = s + "\n" + self.left.__repr__(level+1, indent) ... if self.right: ... s = s + "\n" + self.right.__repr__(level+1, indent) ... return s ... ... def __iter__(self): ... return inorder(self) >>> # Create a Tree from a list. >>> def tree(list): ... n = len(list) ... if n == 0: ... return [] ... i = n // 2 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:])) >>> # Show it off: create a tree. >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") >>> # A recursive generator that generates Tree labels in in-order. >>> def inorder(t): ... if t: ... for x in inorder(t.left): ... yield x ... yield t.label ... for x in inorder(t.right): ... yield x >>> # Show it off: create a tree. >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") >>> # Print the nodes of the tree in in-order. >>> for x in t: ... print x, 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 >>> # A non-recursive generator. >>> def inorder(node): ... stack = [] ... while node: ... while node.left: ... stack.append(node) ... node = node.left ... yield node.label ... while not node.right: ... try: ... node = stack.pop() ... except IndexError: ... return ... yield node.label ... node = node.right >>> # Exercise the non-recursive generator. >>> for x in t: ... print x, 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 s³�� The difference between yielding None and returning it. >>> def g(): ... for i in range(3): ... yield None ... yield None ... return >>> list(g()) [None, None, None, None] Ensure that explicitly raising StopIteration acts like any other exception in try/except, not like a return. >>> def g(): ... yield 1 ... try: ... raise StopIteration ... except: ... yield 2 ... yield 3 >>> list(g()) [1, 2, 3] Next one was posted to c.l.py. >>> def gcomb(x, k): ... "Generate all combinations of k elements from list x." ... ... if k > len(x): ... return ... if k == 0: ... yield [] ... else: ... first, rest = x[0], x[1:] ... # A combination does or doesn't contain first. ... # If it does, the remainder is a k-1 comb of rest. ... for c in gcomb(rest, k-1): ... c.insert(0, first) ... yield c ... # If it doesn't contain first, it's a k comb of rest. ... for c in gcomb(rest, k): ... yield c >>> seq = range(1, 5) >>> for k in range(len(seq) + 2): ... print "%d-combs of %s:" % (k, seq) ... for c in gcomb(seq, k): ... print " ", c 0-combs of [1, 2, 3, 4]: [] 1-combs of [1, 2, 3, 4]: [1] [2] [3] [4] 2-combs of [1, 2, 3, 4]: [1, 2] [1, 3] [1, 4] [2, 3] [2, 4] [3, 4] 3-combs of [1, 2, 3, 4]: [1, 2, 3] [1, 2, 4] [1, 3, 4] [2, 3, 4] 4-combs of [1, 2, 3, 4]: [1, 2, 3, 4] 5-combs of [1, 2, 3, 4]: From the Iterators list, about the types of these things. >>> def g(): ... yield 1 ... >>> type(g) <type 'function'> >>> i = g() >>> type(i) <type 'generator'> >>> [s for s in dir(i) if not s.startswith('_')] ['gi_frame', 'gi_running', 'next'] >>> print i.next.__doc__ x.next() -> the next value, or raise StopIteration >>> iter(i) is i True >>> import types >>> isinstance(i, types.GeneratorType) True And more, added later. >>> i.gi_running 0 >>> type(i.gi_frame) <type 'frame'> >>> i.gi_running = 42 Traceback (most recent call last): ... TypeError: readonly attribute >>> def g(): ... yield me.gi_running >>> me = g() >>> me.gi_running 0 >>> me.next() 1 >>> me.gi_running 0 A clever union-find implementation from c.l.py, due to David Eppstein. Sent: Friday, June 29, 2001 12:16 PM To: python-list@python.org Subject: Re: PEP 255: Simple Generators >>> class disjointSet: ... def __init__(self, name): ... self.name = name ... self.parent = None ... self.generator = self.generate() ... ... def generate(self): ... while not self.parent: ... yield self ... for x in self.parent.generator: ... yield x ... ... def find(self): ... return self.generator.next() ... ... def union(self, parent): ... if self.parent: ... raise ValueError("Sorry, I'm not a root!") ... self.parent = parent ... ... def __str__(self): ... return self.name >>> names = "ABCDEFGHIJKLM" >>> sets = [disjointSet(name) for name in names] >>> roots = sets[:] >>> import random >>> gen = random.WichmannHill(42) >>> while 1: ... for s in sets: ... print "%s->%s" % (s, s.find()), ... print ... if len(roots) > 1: ... s1 = gen.choice(roots) ... roots.remove(s1) ... s2 = gen.choice(roots) ... s1.union(s2) ... print "merged", s1, "into", s2 ... else: ... break 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 merged D into G 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 merged C into F 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 merged L into A 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 merged H into E 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 merged B into E 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 merged J into G 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 merged E into G 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 merged M into G 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 merged I into K 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 merged K into A 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 merged F into A 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 merged A into G 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 s/�� Build up to a recursive Sieve of Eratosthenes generator. >>> def firstn(g, n): ... return [g.next() for i in range(n)] >>> def intsfrom(i): ... while 1: ... yield i ... i += 1 >>> firstn(intsfrom(5), 7) [5, 6, 7, 8, 9, 10, 11] >>> def exclude_multiples(n, ints): ... for i in ints: ... if i % n: ... yield i >>> firstn(exclude_multiples(3, intsfrom(1)), 6) [1, 2, 4, 5, 7, 8] >>> def sieve(ints): ... prime = ints.next() ... yield prime ... not_divisible_by_prime = exclude_multiples(prime, ints) ... for p in sieve(not_divisible_by_prime): ... yield p >>> primes = sieve(intsfrom(2)) >>> firstn(primes, 20) [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71] Another famous problem: generate all integers of the form 2**i * 3**j * 5**k in increasing order, where i,j,k >= 0. Trickier than it may look at first! Try writing it without generators, and correctly, and without generating 3 internal results for each result output. >>> def times(n, g): ... for i in g: ... yield n * i >>> firstn(times(10, intsfrom(1)), 10) [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] >>> def merge(g, h): ... ng = g.next() ... nh = h.next() ... while 1: ... if ng < nh: ... yield ng ... ng = g.next() ... elif ng > nh: ... yield nh ... nh = h.next() ... else: ... yield ng ... ng = g.next() ... nh = h.next() The following works, but is doing a whale of a lot of redundant work -- it's not clear how to get the internal uses of m235 to share a single generator. Note that me_times2 (etc) each need to see every element in the result sequence. So this is an example where lazy lists are more natural (you can look at the head of a lazy list any number of times). >>> def m235(): ... yield 1 ... me_times2 = times(2, m235()) ... me_times3 = times(3, m235()) ... me_times5 = times(5, m235()) ... for i in merge(merge(me_times2, ... me_times3), ... me_times5): ... yield i Don't print "too many" of these -- the implementation above is extremely inefficient: each call of m235() leads to 3 recursive calls, and in turn each of those 3 more, and so on, and so on, until we've descended enough levels to satisfy the print stmts. Very odd: when I printed 5 lines of results below, this managed to screw up Win98's malloc in "the usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting address space, and it *looked* like a very slow leak. >>> result = m235() >>> for i in range(3): ... print firstn(result, 15) [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] [25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] [81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] Heh. Here's one way to get a shared list, complete with an excruciating namespace renaming trick. The *pretty* part is that the times() and merge() functions can be reused as-is, because they only assume their stream arguments are iterable -- a LazyList is the same as a generator to times(). >>> class LazyList: ... def __init__(self, g): ... self.sofar = [] ... self.fetch = g.next ... ... def __getitem__(self, i): ... sofar, fetch = self.sofar, self.fetch ... while i >= len(sofar): ... sofar.append(fetch()) ... return sofar[i] >>> def m235(): ... yield 1 ... # Gack: m235 below actually refers to a LazyList. ... me_times2 = times(2, m235) ... me_times3 = times(3, m235) ... me_times5 = times(5, m235) ... for i in merge(merge(me_times2, ... me_times3), ... me_times5): ... yield i Print as many of these as you like -- *this* implementation is memory- efficient. >>> m235 = LazyList(m235()) >>> for i in range(5): ... print [m235[j] for j in range(15*i, 15*(i+1))] [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] [25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] [81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] [200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384] [400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675] Ye olde Fibonacci generator, LazyList style. >>> def fibgen(a, b): ... ... def sum(g, h): ... while 1: ... yield g.next() + h.next() ... ... def tail(g): ... g.next() # throw first away ... for x in g: ... yield x ... ... yield a ... yield b ... for s in sum(iter(fib), ... tail(iter(fib))): ... yield s >>> fib = LazyList(fibgen(1, 2)) >>> firstn(iter(fib), 17) [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584] s;�� >>> def f(): ... return 22 ... yield 1 Traceback (most recent call last): .. SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2) >>> def f(): ... yield 1 ... return 22 Traceback (most recent call last): .. SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3) "return None" is not the same as "return" in a generator: >>> def f(): ... yield 1 ... return None Traceback (most recent call last): .. SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3) This one is fine: >>> def f(): ... yield 1 ... return >>> def f(): ... try: ... yield 1 ... finally: ... pass Traceback (most recent call last): .. SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[4]>, line 3) >>> def f(): ... try: ... try: ... 1//0 ... except ZeroDivisionError: ... yield 666 # bad because *outer* try has finally ... except: ... pass ... finally: ... pass Traceback (most recent call last): ... SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<doctest test.test_generators.__test__.syntax[5]>, line 6) But this is fine: >>> def f(): ... try: ... try: ... yield 12 ... 1//0 ... except ZeroDivisionError: ... yield 666 ... except: ... try: ... x = 12 ... finally: ... yield 12 ... except: ... return >>> list(f()) [12, 666] >>> def f(): ... yield Traceback (most recent call last): SyntaxError: invalid syntax >>> def f(): ... if 0: ... yield Traceback (most recent call last): SyntaxError: invalid syntax >>> def f(): ... if 0: ... yield 1 >>> type(f()) <type 'generator'> >>> def f(): ... if "": ... yield None >>> type(f()) <type 'generator'> >>> def f(): ... return ... try: ... if x==4: ... pass ... elif 0: ... try: ... 1//0 ... except SyntaxError: ... pass ... else: ... if 0: ... while 12: ... x += 1 ... yield 2 # don't blink ... f(a, b, c, d, e) ... else: ... pass ... except: ... x = 1 ... return >>> type(f()) <type 'generator'> >>> def f(): ... if 0: ... def g(): ... yield 1 ... >>> type(f()) <type 'NoneType'> >>> def f(): ... if 0: ... class C: ... def __init__(self): ... yield 1 ... def f(self): ... yield 2 >>> type(f()) <type 'NoneType'> >>> def f(): ... if 0: ... return ... if 0: ... yield 2 >>> type(f()) <type 'generator'> >>> def f(): ... if 0: ... lambda x: x # shouldn't trigger here ... return # or here ... def f(i): ... return 2*i # or here ... if 0: ... return 3 # but *this* sucks (line 8) ... if 0: ... yield 2 # because it's a generator Traceback (most recent call last): SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[22]>, line 8) This one caused a crash (see SF bug 567538): >>> def f(): ... for i in range(3): ... try: ... continue ... finally: ... yield i ... >>> g = f() >>> print g.next() 0 >>> print g.next() 1 >>> print g.next() 2 >>> print g.next() Traceback (most recent call last): StopIteration c���������#���sD���d��g�t�ˆ��ƒ�}�|�‡��‡�d�†�‰�x�ˆ�d�ƒ�D] �}�|�Vq2�Wd��S(���Nc���������#���sZ���|��t�ˆ��ƒ�j�o�|�Vn<�x8�ˆ��|��ƒ��D])�|�|��<x�ˆ�|��d�ƒ�D] �}�|�VqD�Wq)�Wd��S(���Ni���(���t���it���lent���gst���valuest���gent���x(���R����R���R���(���R���R���(����t*���/usr/lib/python2.4/test/test_generators.pyR���W��s����� �i����(���t���NoneR���R���R���R���R���(���R���R���R���R���(����(���R���R���R���t���conjoinS��s ���� �c������ ���#���se���t��ˆ��ƒ�‰�d��g�ˆ�}�|�‡��‡�‡�‡�d�†�‰�|�‡��‡�‡�d�†�‰�x�ˆ�d�ƒ�D] �}�|�VqS�Wd��S(���Nc���������#���sˆ���|��ˆ�j�o�|�Vnp�ˆ�|��d�oE�|��d�}�xS�ˆ��|��ƒ��D]%�|�|��<x�ˆ�|�ƒ�D] �}�|�VqS�Wq<�Wn�x�ˆ�|��ƒ�D] �}�|�Vqv�Wd��S(���Ni���i���(���R����t���nR���t���ip1R���R���R���t���_gen3(���R����R���R ���R���(���R���R ���R���R���(����R���R���p��s���� � � �c��� ������#���s#��|��ˆ�j��o�ˆ�|��d�d�j�p�t�‚�|��d�|��d�|��d�}�}�}�ˆ��|��|�!\�}�}�}�|�ˆ�j�oP�x°�|�ƒ��D]>�|�|��<x1�|�ƒ��D]&�|�|�<x�|�ƒ��D]�|�|�<|�Vqž�WqŠ�Wqv�Wnd�x`�|�ƒ��D]U�|�|��<xH�|�ƒ��D]=�|�|�<x0�|�ƒ��D]%�|�|�<x�ˆ�|�ƒ�D] �}�|�VqWqî�WqÚ�WqÆ�Wd��S(���Ni���i����i���i���( ���R����R ���t���AssertionErrorR ���t���ip2t���ip3R���t���gt���g1t���g2R���R���R���( ���R����R���R���R���R ���R���R ���R���R���(���R���R ���R���(����R���R���‚��s(����) � � � � � � �i����(���R���R���R ���R���R���R���R���R���(���R���R ���R���R���R���R���(����(���R���R���R���R ���R���R���h��s���� �c���������c���s(��t��|��ƒ�}�d��g�|�}�d��g�|�}�t�}�d�}�xï�yH�xA�|�|�j��o3�|��|�ƒ��i �}�|�|�<|�ƒ��|�|�<|�d�7}�q;�WWn�|�j �o�n�X|�|�j�p�t�‚�|�V|�d�8}�xg�|�d�j�oD�y �|�|�ƒ��|�|�<|�d�7}�PWq¸�|�j �o�|�d�8}�q¸�Xq¸�W|�d�j��p�t�‚�Pq5�Wd��S(���Ni����i���(���R���R���R ���R���R���t���iterst ���StopIterationt���_StopIterationR����t���nextt���itR���(���R���R���R���R ���R����R���R���(����(����R���t���flat_conjoin¥��s8���� ��� � t���Queensc�����������B���s#���t��Z�d�„��Z�d�„��Z�d�„��Z�RS(���Nc������ ������s®���|�ˆ��_��t�|�ƒ�‰�g��ˆ��_�x‰�ˆ�D]�}�g��}�ˆ�D]E�}�|�d�|�>d�|�|�|�|�d�>Bd�|�d�|�d�|�|�>Bq6�~�}�|�‡��‡�d�†�}�ˆ��i�i �|�ƒ�q%�Wd��S(���Nl����i���i���c���������#���sZ���xS�ˆ�D]K�}�|��|�}�|�ˆ��i�@d�j�o'�ˆ��i�|�O_�|�Vˆ��i�|�M_�q�q�Wd��S(���Ni����(���t���rangent���jt���rowusest���usest���selft���used(���R���R���R���(���R���R���(����R���t���rowgenà��s����� (���R ���R���t���rangeR���t ���rowgeneratorsR����t���_[1]R���R���R���t���append(���R���R ���R���R����R���R���R"���R���(����(���R���R���R���t���__init__Ê��s���� �Yc���������c���s+���d�|��_�x�t�|��i�ƒ�D] �}�|�Vq�Wd��S(���Ni����(���R���R���R���R!���t���row2col(���R���R%���(����(����R���t���solveë��s���� �c���������C���s¡���|��i�}�|�t�|�ƒ�j�p�t�‚�d�d�|�}�|�GHxd�t�|�ƒ�D]V�}�g��}�t�|�ƒ�D] �}�|�d�qZ�~�}�d�|�|�|�<d�d�i�|�ƒ�d�GH|�GHqC�Wd��S(���Nt���+s���-+t��� t���Qt���|(���R���R ���R���R%���R���t���sepR ���R����R"���R���t���squarest���join(���R���R%���R+���R����R���R ���R"���R,���(����(����R���t ���printsolutionð��s���� �'(���t���__name__t ���__module__R$���R&���R.���(����(����(����R���R���É��s��� ! t���Knightsc�����������B���sA���t��Z�d�d�„�Z�d�„��Z�d�„��Z�d�„��Z�d�„��Z�d�„��Z�RS(���Ni����c������������s��ˆ�ˆ�ˆ��_��ˆ��_�g��‰�ˆ��_�t�‡�d�†�‰�‡�d�†��‰�‡��‡�‡�‡�‡�d�†��}�‡��‡�‡�‡�‡�‡�d�†��}�t�‡��‡�‡�‡�d�†�}�ˆ�d�d�ˆ�d�d�t�‡��‡�‡�‡�d�†�} �‡��‡�d �†��}�ˆ�ˆ�d �j��o�|�g�ˆ��_�n8�|�|�g�|�o�| �p�|�g�ˆ�ˆ�d�|�g�ˆ��_�d��S(���Nc������������s���d�}�}�xk�ˆ��|��D]_�}�ˆ��|�}�|�i�|��ƒ�|�|�ƒ�}�|�d�j�o�|�d�7}�q�|�d�j�o�|�d�7}�q�q�W|�d�j�o �|�d�j��S(���Ni����i���i���( ���t���ne0t���ne1t���succst���i0R����t���st���removeR���t���e(���R5���R���R8���R����R6���R2���R3���(���R4���(����R���t���remove_from_successors��s���� � c������������s*���x#�ˆ��|��D]�}�ˆ��|�i�|��ƒ�q�Wd��S(���N(���R4���R5���R����R#���(���R5���R����(���R4���(����R���t���add_to_successors"��s�����c����������#���sY���ˆ�d�j��p �ˆ�d�j��o�d��Sn�ˆ��i�d�d�ƒ�}��ˆ�|��ƒ�|��ˆ��_�|��Vˆ�|��ƒ�d��S(���Ni���i����(���t���mR ���R���t���coords2indext���cornerR9���t���lastijR:���(���R=���(���R���R;���R ���R9���R:���(����R���t���first'��s���� c����������#���sJ��ˆ��i�d�d�ƒ�}�ˆ��i�|�j�p�t�‚�ˆ�d�j��p �ˆ�d�j��o�d��Sn�t�ˆ�|�ƒ�d�j�p�t�‚�ˆ��i�d�d�ƒ�ˆ�|�j�p�t�‚�ˆ��i�d�d�ƒ�ˆ�|�j�p�t�‚�x’�d�d�f�D]„�\�}��}�ˆ��i�|��|�ƒ�}�ˆ��i�d�|��d�|�ƒ�}�|�ˆ��_�ˆ�|�ƒ�ˆ�|�i�|�ƒ�|�ˆ��_�|�Vˆ�|�i�|�ƒ�ˆ�|�ƒ�q¾�Wd��S(���Ni����i���i���i���(���i���i���(���i���i���(���R���R<���R=���R>���R���R;���R ���R���R4���R����R���t���thist���finalR9���R#���R7���R:���(���R����R���R@���R=���RA���(���R���R;���R ���R4���R9���R:���(����R���t���second4��s$����$$ � c���������#���sÚ���g��}�xz�ˆ�ˆ��i�D]a�}�|��ˆ�|�ƒ�}�|�d�j�p �t�d�‚�|�d�j�o�|�|�f�g�}�Pn�|�i�|�|�f�ƒ�q�W|�i �ƒ��xP�|�D]H�\�}�}�|�ˆ��i �j�o,�ˆ�|�ƒ�o�|�ˆ��_�|�Vn�ˆ�|�ƒ�qŠ�qŠ�Wd��S(���Ni����s,���else remove_from_successors() pruning flawedi���( ���t ���candidatesR4���R���R>���R����R���R8���R���R#���t���sortRA���R9���R:���(���R���R8���R����RC���(���R���R4���R9���R:���(����R���t���advanceM��s"����� � i���f2.0c��� ������#���s��g��}�x°�ˆ�ˆ��i�D]—�}�|�ˆ�|�ƒ�}�|�d�j�p �t�d�‚�|�d�j�o�|�d�|�f�g�}�Pn�ˆ��i�|�ƒ�\�}�}�|�|��d�|�|�d�}�|�i�|�|�|�f�ƒ�q�W|�i�ƒ��xS�|�D]K�\�}�}�}�|�ˆ��i�j�o,�ˆ�|�ƒ�o�|�ˆ��_�|�Vn�ˆ�|�ƒ�qÀ�qÀ�Wd��S(���Ni����s,���else remove_from_successors() pruning flawedi���i���(���RC���R4���R���R>���R����R���R8���R���t���index2coordst���i1t���j1t���vmidt���hmidt���dR#���RD���RA���R9���R:���( ���RI���RJ���R���R8���RK���R����RH���RG���RC���(���R���R9���R4���R:���(����R���t���advance_hardg��s&����� � c�����������#���s)���ˆ��i�ˆ�ˆ��i�j�p�t�‚�ˆ��i�Vd��S(���N(���R���RA���R4���R>���R���(����(���R���R4���(����R���t���last��s����i���i���(���R;���R ���R���R4���R���R9���R:���R?���RB���RE���RL���RM���t���squaregeneratorst���hard(���R���R;���R ���RO���RE���RM���RB���R4���R9���R:���RL���R?���(����(���R���R;���R ���R4���R9���R:���R���R$�����s���� .c���������C���s_���d�|�j�o �|��i�j��n�p�t�‚�d�|�j�o �|��i�j��n�p�t�‚�|�|��i�|�S(���Ni����(���R����R���R;���R���R���R ���(���R���R����R���(����(����R���R<���Œ��s����((c���������C���s?���d�|�j�o�|��i�|��i�j��n�p�t�‚�t�|�|��i�ƒ�S(���Ni����(���t���indexR���R;���R ���R���t���divmod(���R���RP���(����(����R���RF���‘��s����/c��� ��� ���C���s��|��i�} �| �2|��i�|��i�}�}�|��i�}�d�d�d�d �d �d�d�d �g�}�t�|�ƒ�}�x²�t�|�ƒ�D]¤�}�x›�|�D]“�}�g��}�|�D]l�\�}�} �d�|�|�j�o �|�j��n�o>�d�|�| �j�o �|�j��n�o�|�|�|�|�|�| �ƒ�q~�q~�~�}�| �i�|�ƒ�qm�Wq`�Wd��S(���Ni���i���iÿÿÿÿiþÿÿÿi����(���i���i���(���i���i���(���i���iÿÿÿÿ(���i���iþÿÿÿ(���iÿÿÿÿiþÿÿÿ(���iþÿÿÿiÿÿÿÿ(���iþÿÿÿi���(���iÿÿÿÿi���(���R���R4���R;���R ���R<���t���c2it���offsetsR ���R���R����R���R"���t���iot���joR6���R#���( ���R���RS���R����R6���R���R;���R���R ���R"���RU���R4���RT���RR���(����(����R���t���_init_board•��s���� ��€c���������c���s,���|��i�ƒ��x�t�|��i�ƒ�D] �}�|�Vq�Wd��S(���N(���R���RV���R���RN���R���(���R���R���(����(����R���R&���¦��s���� �c���������C���s,��|��i�|��i�}�}�t�|�ƒ�|�|�j�p�t�‚�t�t�|�|�ƒ�ƒ�} �d�t�| �ƒ�d�}�g��}�t �|�ƒ�D]�}�|�d��g�|�ql�~�}�d�}�x?�|�D]7�}�|��i�|�ƒ�\�} �}�|�|�|�| �|�<|�d�7}�q–�Wd�d�| �d�|�}�|�GHx9�t �|�ƒ�D]+�}�|�|�} �d�d�i�| �ƒ�d�GH|�GHqù�Wd��S(���Nt���%RK���i���R'���t���-R*���(���R���R;���R ���R���R���R���t���strt���wt���formatR"���R ���R����R���R,���t���kRF���RG���RH���R+���t���rowR-���(���R���R���R[���R����R+���R;���RH���R ���R"���RG���RZ���R,���R\���R]���(����(����R���R.���«��s$����.� � (���R/���R0���R$���R<���RF���RV���R&���R.���(����(����(����R���R1������s���‹ s`�� Generate the 3-bit binary numbers in order. This illustrates dumbest- possible use of conjoin, just to generate the full cross-product. >>> for c in conjoin([lambda: iter((0, 1))] * 3): ... print c [0, 0, 0] [0, 0, 1] [0, 1, 0] [0, 1, 1] [1, 0, 0] [1, 0, 1] [1, 1, 0] [1, 1, 1] For efficiency in typical backtracking apps, conjoin() yields the same list object each time. So if you want to save away a full account of its generated sequence, you need to copy its results. >>> def gencopy(iterator): ... for x in iterator: ... yield x[:] >>> for n in range(10): ... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n))) ... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n 0 1 True True 1 2 True True 2 4 True True 3 8 True True 4 16 True True 5 32 True True 6 64 True True 7 128 True True 8 256 True True 9 512 True True And run an 8-queens solver. >>> q = Queens(8) >>> LIMIT = 2 >>> count = 0 >>> for row2col in q.solve(): ... count += 1 ... if count <= LIMIT: ... print "Solution", count ... q.printsolution(row2col) Solution 1 +-+-+-+-+-+-+-+-+ |Q| | | | | | | | +-+-+-+-+-+-+-+-+ | | | | |Q| | | | +-+-+-+-+-+-+-+-+ | | | | | | | |Q| +-+-+-+-+-+-+-+-+ | | | | | |Q| | | +-+-+-+-+-+-+-+-+ | | |Q| | | | | | +-+-+-+-+-+-+-+-+ | | | | | | |Q| | +-+-+-+-+-+-+-+-+ | |Q| | | | | | | +-+-+-+-+-+-+-+-+ | | | |Q| | | | | +-+-+-+-+-+-+-+-+ Solution 2 +-+-+-+-+-+-+-+-+ |Q| | | | | | | | +-+-+-+-+-+-+-+-+ | | | | | |Q| | | +-+-+-+-+-+-+-+-+ | | | | | | | |Q| +-+-+-+-+-+-+-+-+ | | |Q| | | | | | +-+-+-+-+-+-+-+-+ | | | | | | |Q| | +-+-+-+-+-+-+-+-+ | | | |Q| | | | | +-+-+-+-+-+-+-+-+ | |Q| | | | | | | +-+-+-+-+-+-+-+-+ | | | | |Q| | | | +-+-+-+-+-+-+-+-+ >>> print count, "solutions in all." 92 solutions in all. And run a Knight's Tour on a 10x10 board. Note that there are about 20,000 solutions even on a 6x6 board, so don't dare run this to exhaustion. >>> k = Knights(10, 10) >>> LIMIT = 2 >>> count = 0 >>> for x in k.solve(): ... count += 1 ... if count <= LIMIT: ... print "Solution", count ... k.printsolution(x) ... else: ... break Solution 1 +---+---+---+---+---+---+---+---+---+---+ | 1| 58| 27| 34| 3| 40| 29| 10| 5| 8| +---+---+---+---+---+---+---+---+---+---+ | 26| 35| 2| 57| 28| 33| 4| 7| 30| 11| +---+---+---+---+---+---+---+---+---+---+ | 59|100| 73| 36| 41| 56| 39| 32| 9| 6| +---+---+---+---+---+---+---+---+---+---+ | 74| 25| 60| 55| 72| 37| 42| 49| 12| 31| +---+---+---+---+---+---+---+---+---+---+ | 61| 86| 99| 76| 63| 52| 47| 38| 43| 50| +---+---+---+---+---+---+---+---+---+---+ | 24| 75| 62| 85| 54| 71| 64| 51| 48| 13| +---+---+---+---+---+---+---+---+---+---+ | 87| 98| 91| 80| 77| 84| 53| 46| 65| 44| +---+---+---+---+---+---+---+---+---+---+ | 90| 23| 88| 95| 70| 79| 68| 83| 14| 17| +---+---+---+---+---+---+---+---+---+---+ | 97| 92| 21| 78| 81| 94| 19| 16| 45| 66| +---+---+---+---+---+---+---+---+---+---+ | 22| 89| 96| 93| 20| 69| 82| 67| 18| 15| +---+---+---+---+---+---+---+---+---+---+ Solution 2 +---+---+---+---+---+---+---+---+---+---+ | 1| 58| 27| 34| 3| 40| 29| 10| 5| 8| +---+---+---+---+---+---+---+---+---+---+ | 26| 35| 2| 57| 28| 33| 4| 7| 30| 11| +---+---+---+---+---+---+---+---+---+---+ | 59|100| 73| 36| 41| 56| 39| 32| 9| 6| +---+---+---+---+---+---+---+---+---+---+ | 74| 25| 60| 55| 72| 37| 42| 49| 12| 31| +---+---+---+---+---+---+---+---+---+---+ | 61| 86| 99| 76| 63| 52| 47| 38| 43| 50| +---+---+---+---+---+---+---+---+---+---+ | 24| 75| 62| 85| 54| 71| 64| 51| 48| 13| +---+---+---+---+---+---+---+---+---+---+ | 87| 98| 89| 80| 77| 84| 53| 46| 65| 44| +---+---+---+---+---+---+---+---+---+---+ | 90| 23| 92| 95| 70| 79| 68| 83| 14| 17| +---+---+---+---+---+---+---+---+---+---+ | 97| 88| 21| 78| 81| 94| 19| 16| 45| 66| +---+---+---+---+---+---+---+---+---+---+ | 22| 91| 96| 93| 20| 69| 82| 67| 18| 15| +---+---+---+---+---+---+---+---+---+---+ sM��Generators are weakly referencable: >>> import weakref >>> def gen(): ... yield 'foo!' ... >>> wr = weakref.ref(gen) >>> wr() is gen True >>> p = weakref.proxy(gen) Generator-iterators are weakly referencable as well: >>> gi = gen() >>> wr = weakref.ref(gi) >>> wr() is gi True >>> p = weakref.proxy(gi) >>> list(p) ['foo!'] t���tutt���pept���emailt���funt���syntaxR���t���weakrefc���������C���s'���d�k��l�}�l�}�|�i�|�|��ƒ�d��S(���N(���s���test_supports���test_generators(���t���testt���test_supportt���test_generatorst���run_doctestt���verbose(���Rh���Re���Rf���(����(����R���t ���test_mainw��s����t���__main__i���N(���t���tutorial_testst ���pep_testst���email_testst ���fun_testst���syntax_testsR���R���R���R1���t ���conjoin_testst ���weakref_testst���__test__R���Ri���R/���( ���Rn���Ro���Rp���R���Rm���Rk���R���Rl���Ri���Rr���Rq���R1���R���(����(����R���t���?���s���‡¥½ É = $7¿“E