Python multiplication table syntax differences
Question: So I'm learning python as a beginner and have been using How to Think Like a
Computer Scientist for python 3. I'm on the chapter about iteration, doing the
coding from my own brain instead of copy/pasting so I remember it easier.

When doing the last part of the multiplication table section, I got the same
output as the lesson showed, but it seems like mine is cleaner (fewer
arguments). I'm still trying to get the hang of tracing programs, so I'm
having a hard time wrapping my head around the differences. I was hoping
someone could let me know if my code is less efficient or more error prone
somehow than the text's version and help end this headache ;).

    
    
    def print_multiples(n, high):         #This is the e-book version
        for i in range(1, high+1):
            print(n * i, end='   ')
        print()
    
    def print_mult_table(high):
        for i in range(1, high+1):
            print_multiples(i, i+1)       #They changed high+1 to i+1 to halve output
    

[Source](http://openbookproject.net/thinkcs/python/english3e/iteration.html
"e-book source")

It seems like their result would have too many +1's, since i+1 would become
'high' in print_multiples and then end up adding +1 again in print_multiples'
loop. (I also noticed they kept the end=' ' instead of a end='\t' which threw
off alignment.

    
    
    def print_multiples(n):         #n is the number of columns that will be made
        '''Prints a line of multiples of factor 'n'.'''
        for x in range(1, n+1):     #prints n  2n  3n ... until x = n+1
            print(n * x, end='\t')  #(since x starts counting at 0, 
        print()                     #n*n will be the final entry)
    
    
    def print_mult_table(n):            #n is the final factor
        '''Makes a table from a factor 'n' via print_multiples().
        '''
        for i in range(1, n+1):         #call function to print rows with i
            print_multiples(i)          #as the multiplier.
    

This is mine. The elementary comments were for my benefit trying to keep the
tracing straight in my head. My functions make a lot more sense to me, but
there could be some difference. I don't really understand why the book decided
to make two arguments for print_multiples() since 1 seems sufficient to me...I
also changed most of the variables since they were using 'i' and 'high'
multiple times to demonstrate local vs global. I re-used n, though, since it
would be the same final number in both cases.

There might be more efficient ways to do this type of thing, but I'm still on
iteration. Just hoping to try to get a feel for what works and what doesn't
and this one is bugging me.


Answer: (Note: right, you're running Python 3.x)  
Your code is simpler and makes more sense to me, too.  
Theirs is correct, but its intention is not quite the same, so its output is
different.  
Carefully compare the outputs of both and see if you can notice the pattern of
difference.

Your code is slightly more "efficient", but printing stuff to the screen takes
a (relatively) long time, and your program prints slightly less than theirs.

To measure efficiency, you can "profile" code in Python to see how long things
take. Below is the code I ran to  
a) inspect the difference in source text and output  
b) profile the code to see which was faster.  
You might try running it. Good luck!

    
    
    import cProfile
    
    def print_multiples0(n, high):         #This is the e-book version
        for i in range(1, high+1):
            print(n * i, end='   ')
        print()
    
    def print_mult_table0(high):
        for i in range(1, high+1):
            print_multiples0(i, i+1)       #They changed high+1 to i+1 to halve output
    
    def print_multiples1(n):        #n is the number of columns that will be made
        '''Prints a line of multiples of factor 'n'.'''
        for x in range(1, n+1):     #prints n  2n  3n ... until x = n+1
            print(n * x, end='\t')  #(since x starts counting at 0,
        print()                     #n*n will be the final entry)
    
    def print_mult_table1(n):            #n is the final factor
        '''Makes a table from a factor 'n' via print_multiples().
        '''
        for i in range(1, n+1):          #call function to print rows with i
            print_multiples1(i)          #as the multiplier.
    
    def test( ) :
         print_mult_table0( 10)
         print_mult_table1( 10)
    
    cProfile.run( 'test()')
    

