'''  version 2 with doctests.
This code illustrates the standard Python idioms for multiple
assignment.  In class we used multiple assignment, but only with an
explicit comma-separated sequence on both sides of the equal sign. More
generally:  the right-hand side can be *any* expression generating a
tuple, for instance a tuple return value. In particular, this can be
used in a recursive function returning a tuple.

There is an implicit assignment to the loop variable in the heading of
a for-loop.  This assignment can also be multiple when the elements in
the for-loop's sequence are tuples. In my testing function I
illustrate this.  You can see how handy it is.  A variation on this
testing function would also be convenient for testing your homework.

Doctests look like manual tests run in the Python shell, starting with >>>.  
They are most simply embedded in function, class, and module documentation strings, like below in this module documentation string:

>>> threePowers(-4, 5)
(-1024, 4096, -16384)

The code at the end of this module automatically runs all such tests.  
Also see the notes and doctests in the doc strings for functions 
threePowers and doctests.
'''

def threePowers(x, n):
    ''' Return (x**n, x**(n+1), x**(n+2) ) for small nonnegative
    integer n. This is a silly algorithm, but it illustrates recursion
    and multiple assignment.

    Current function doctests are very handy to illustrate use and
    provide simple tests.  Lengthy edge tests are usually elsewhere.

    >>> threePowers(3, 0)
    (1, 3, 9)
    >>> threePowers(2, 7)
    (128, 256, 512)
    >>> threePowers(-1, 27)
    (-1, 1, -1)
    >>> threePowers(100, 8)
    (10000000000000000, 1000000000000000000, 100000000000000000000L)
    '''
    if n == 0:
        return (1, x, x*x)
    a, b, c = threePowers(x, n-1)
    return b, c, c*x

def testing():
    '''explicit coding of test to illustrate for-loop multiple assignment
    - doctest is handier!
    '''
    for (x, n) in [(3, 0), (2, 7), (-1, 27), (100, 8)]:
        pn, pn1, pn2 = threePowers(x, n)
        print 'x:', x, 'n:', n, 'powers:', pn, pn1, pn2
        if (pn, pn1, pn2) != (x**n, x**(n+1), x**(n+2)):
            print "ERROR"
            print (pn, pn1, pn2), '!=', (x**n, x**(n+1), x**(n+2))

def doctests():
    '''
    Further doctest notes:

    It is good to put a few doctests in a regular function definition,
    including cases that illustrate the usual syntax for the function.
    
    A separate function wih just a docstring is handy for tests that are
    important for edge cases but do not illuminate the basic behavior for the
    user, or involve interaction of multiple functions. (In this simple
    module, ther is really no call for extras.)

    Doctests are separated from other comments in the doc string by blanks lines. 

    The doctest below, similar to the testing function above,
    illustrates how a compound statement with a heading is entered in
    a doctest, with the "...".  This is exactly the form of the
    interactive shell for python.  A direct copy of a compound
    statement entered into the *idle* shell does not work, because
    idle automatically indents and starts continuation lines with blanks,
    not '...'.

    >>> for (x, n) in [(3, 0), (2, 7), (-1, 27), (100, 8)]:
    ...     pn, pn1, pn2 = threePowers(x, n)
    ...     print pn, pn1, pn2
    1 3 9
    128 256 512
    -1 1 -1
    10000000000000000 1000000000000000000 100000000000000000000

    Be careful of trailing whitespace.  A test cam be marked wrong when the
    displayed output looks the same as what you asked for.  In that case you
    likely need to remove the trailing white space in the doctest response.
    For instance if there were a blank after 512 above, the test would fail.
    Though idle automatically strips trailing blanks in code lines, inside
    multiline strings is an exception to the rule.
    
    There are many fancier options for doctest.
    There is also a unittest module also, in the flavor of JUnit.
    '''
    # no body - just here for the doctest.

if __name__ == '__main__': # good standard lines for a library, not a script.
    # code for automatic complete doctests
    import doctest 
    doctest.testmod(verbose=True) # verbose good initially - checks all found
#    doctest.testmod() # This version is silent on success
    
#    testing() # old test version
