Back to index

python3.2  3.2.2
Classes | Functions | Variables
test.test_generators Namespace Reference

Classes

class  Queens
class  Knights

Functions

def simple_conjoin
def conjoin
def flat_conjoin
def test_main

Variables

string tutorial_tests
string pep_tests
string email_tests
string fun_tests
string syntax_tests
string conjoin_tests
string weakref_tests
string coroutine_tests
string refleaks_tests
dictionary __test__

Function Documentation

Definition at line 984 of file test_generators.py.

00984 
00985 def conjoin(gs):
00986 
00987     n = len(gs)
00988     values = [None] * n
00989 
00990     # Do one loop nest at time recursively, until the # of loop nests
00991     # remaining is divisible by 3.
00992 
00993     def gen(i):
00994         if i >= n:
00995             yield values
00996 
00997         elif (n-i) % 3:
00998             ip1 = i+1
00999             for values[i] in gs[i]():
01000                 for x in gen(ip1):
01001                     yield x
01002 
01003         else:
01004             for x in _gen3(i):
01005                 yield x
01006 
01007     # Do three loop nests at a time, recursing only if at least three more
01008     # remain.  Don't call directly:  this is an internal optimization for
01009     # gen's use.
01010 
01011     def _gen3(i):
01012         assert i < n and (n-i) % 3 == 0
01013         ip1, ip2, ip3 = i+1, i+2, i+3
01014         g, g1, g2 = gs[i : ip3]
01015 
01016         if ip3 >= n:
01017             # These are the last three, so we can yield values directly.
01018             for values[i] in g():
01019                 for values[ip1] in g1():
01020                     for values[ip2] in g2():
01021                         yield values
01022 
01023         else:
01024             # At least 6 loop nests remain; peel off 3 and recurse for the
01025             # rest.
01026             for values[i] in g():
01027                 for values[ip1] in g1():
01028                     for values[ip2] in g2():
01029                         for x in _gen3(ip3):
01030                             yield x
01031 
01032     for x in gen(0):
01033         yield x
01034 
01035 # And one more approach:  For backtracking apps like the Knight's Tour
01036 # solver below, the number of backtracking levels can be enormous (one
01037 # level per square, for the Knight's Tour, so that e.g. a 100x100 board
01038 # needs 10,000 levels).  In such cases Python is likely to run out of
01039 # stack space due to recursion.  So here's a recursion-free version of
01040 # conjoin too.
01041 # NOTE WELL:  This allows large problems to be solved with only trivial
01042 # demands on stack space.  Without explicitly resumable generators, this is
01043 # much harder to achieve.  OTOH, this is much slower (up to a factor of 2)
01044 # than the fancy unrolled recursive conjoin.

Here is the caller graph for this function:

Definition at line 1045 of file test_generators.py.

01045 
01046 def flat_conjoin(gs):  # rename to conjoin to run tests with this instead
01047     n = len(gs)
01048     values = [None] * n
01049     iters  = [None] * n
01050     _StopIteration = StopIteration  # make local because caught a *lot*
01051     i = 0
01052     while 1:
01053         # Descend.
01054         try:
01055             while i < n:
01056                 it = iters[i] = gs[i]().__next__
01057                 values[i] = it()
01058                 i += 1
01059         except _StopIteration:
01060             pass
01061         else:
01062             assert i == n
01063             yield values
01064 
01065         # Backtrack until an older iterator can be resumed.
01066         i -= 1
01067         while i >= 0:
01068             try:
01069                 values[i] = iters[i]()
01070                 # Success!  Start fresh at next level.
01071                 i += 1
01072                 break
01073             except _StopIteration:
01074                 # Continue backtracking.
01075                 i -= 1
01076         else:
01077             assert i < 0
01078             break
01079 
01080 # A conjoin-based N-Queens solver.

Definition at line 963 of file test_generators.py.

00963 
00964 def simple_conjoin(gs):
00965 
00966     values = [None] * len(gs)
00967 
00968     def gen(i):
00969         if i >= len(gs):
00970             yield values
00971         else:
00972             for values[i] in gs[i]():
00973                 for x in gen(i+1):
00974                     yield x
00975 
00976     for x in gen(0):
00977         yield x
00978 
00979 # That works fine, but recursing a level and checking i against len(gs) for
00980 # each item produced is inefficient.  By doing manual loop unrolling across
00981 # generator boundaries, it's possible to eliminate most of that overhead.
00982 # This isn't worth the bother *in general* for generators, but conjoin() is
00983 # a core building block for some CPU-intensive generator applications.

def test.test_generators.test_main (   verbose = None)

Definition at line 1897 of file test_generators.py.

01897 
01898 def test_main(verbose=None):
01899     from test import support, test_generators
01900     support.run_doctest(test_generators, verbose)
01901 
# This part isn't needed for regrtest, but for running the test directly.

Variable Documentation

Initial value:
00001 {"tut":      tutorial_tests,
00002             "pep":      pep_tests,
00003             "email":    email_tests,
00004             "fun":      fun_tests,
00005             "syntax":   syntax_tests,
00006             "conjoin":  conjoin_tests,
00007             "weakref":  weakref_tests,
00008             "coroutine":  coroutine_tests,
00009             "refleaks": refleaks_tests,
00010             }

Definition at line 1882 of file test_generators.py.

Definition at line 1327 of file test_generators.py.

Definition at line 1498 of file test_generators.py.

Definition at line 301 of file test_generators.py.

Definition at line 491 of file test_generators.py.

Definition at line 136 of file test_generators.py.

Definition at line 1807 of file test_generators.py.

Definition at line 729 of file test_generators.py.

Definition at line 1 of file test_generators.py.

Initial value:
00001 """\
00002 Generators are weakly referencable:
00003 
00004 >>> import weakref
00005 >>> def gen():
00006 ...     yield 'foo!'
00007 ...
00008 >>> wr = weakref.ref(gen)
00009 >>> wr() is gen
00010 True
00011 >>> p = weakref.proxy(gen)
00012 
00013 Generator-iterators are weakly referencable as well:
00014 
00015 >>> gi = gen()
00016 >>> wr = weakref.ref(gi)
00017 >>> wr() is gi
00018 True
00019 >>> p = weakref.proxy(gi)
00020 >>> list(p)
00021 ['foo!']
00022 
00023 """

Definition at line 1474 of file test_generators.py.