Loops and Functions

For more verbose explanation of what's going on here, a good place to look is at the following section of the Python tutorial: http://docs.python.org/tutorial/controlflow.html

While Loops

While loops tend not to be used nearly as much as for loops in Python code.

{{{id=8| i = 0 while i < 10: print i i += 1 /// }}} {{{id=9| i = 0 while i < 10: if i % 2 == 1: i += 1 continue print i i += 1 /// }}}

Note that the truth value expression in the while loop is evaluated using bool().

{{{id=54| bool(True) /// }}} {{{id=39| bool('a') /// }}} {{{id=57| bool(1) /// }}} {{{id=55| bool(0) /// }}} {{{id=56| i = 4 while i: print i i -= 1 /// }}} {{{id=52| /// }}} {{{id=38| /// }}}

For Loops

 

Here is a basic for loop iterating over all of the elements in the list l:

{{{id=1| l = ['a', 'b', 'c'] for letter in l: print letter /// }}} {{{id=12| /// }}}

The range function is very useful when you want to generate arithmetic progressions to loop over.  Note that the end point is never included:

{{{id=19| range? /// }}} {{{id=3| range(4) /// }}} {{{id=14| range(1, 5) /// }}} {{{id=15| range(1, 11, 2) /// }}} {{{id=16| range(10, 0, -1) /// }}} {{{id=17| /// }}} {{{id=4| for i in range(4): print i, i*i /// }}}

You can use the continue keyword to immediately go to the next item in the loop:

{{{id=5| for i in range(10): if i % 2 == 0: continue print i /// }}} {{{id=23| /// }}}

If you want to break out of the loop, use the break keyword:

{{{id=6| for i in range(10): if i % 2 == 0: continue if i == 7: break print i /// }}} {{{id=7| /// }}}

If you need to keep track of both the position in the list and its value, one (not so elegant) way would be to do the following:

{{{id=31| l = ['a', 'b', 'c'] for i in range(len(l)): print i, l[i] /// }}} {{{id=32| /// }}}

It's cleaner to use enumerate which provides the index as well as the value:

{{{id=26| l = ['a', 'b', 'c'] for i, letter in enumerate(l): print i, letter /// }}} {{{id=35| /// }}}

You could make something similary to the enumerate function by using zip to zip two lists together:

{{{id=34| l = ['a', 'b', 'c'] for i, letter in zip(range(len(l)), l): print i, letter /// }}} {{{id=28| /// }}}

For loops work using Python's iterator protocol.  This allows all sorts of different objects to be looped over.  For example,

{{{id=41| for i in GF(5): print i, i*i /// }}}

How does it work?

{{{id=27| it = iter(GF(5)); it /// }}} {{{id=47| it.next() /// }}} {{{id=45| it.next() /// }}} {{{id=46| it.next() /// }}} {{{id=48| it.next() /// }}} {{{id=49| it.next() /// }}} {{{id=50| it.next() /// }}} {{{id=44| R = GF(5) /// }}} {{{id=51| R.__iter__?? /// }}}

yield provides a very convient way to produce iterators.  We'll see more about it in a bit.

{{{id=25| /// }}}

Functions

Functions are defined using the def statement, and values are returned using the return keyword.

{{{id=62| def f(x): return x*x /// }}} {{{id=59| f(2) /// }}} {{{id=91| def fib(n): if n <= 1: return 1 else: return fib(n-1) + fib(n-2) /// }}} {{{id=90| [fib(i) for i in range(10)] /// }}} {{{id=89| /// }}}

Functions are first class objects like any other.  For example, they can be passed in as arguments to other functions.

{{{id=71| f /// }}} {{{id=63| def compose(f, x, n): for i in range(n): x = f(x) return x /// }}} {{{id=64| compose(f, 2, 3) /// }}} {{{id=10| def add_one(x): return x + 1 /// }}} {{{id=65| compose(add_one, 2, 3) /// }}} {{{id=69| /// }}}

You can give default values for arguments in functions:

{{{id=72| def add_n(x, n=1): return x + n /// }}} {{{id=68| add_n(4) /// }}} {{{id=73| /// }}} {{{id=67| add_n(4, n=100) /// }}} {{{id=74| add_n(4, 1000) /// }}}

You can return multiple things from a function:

{{{id=76| def g(x): return x, x*x /// }}} {{{id=79| g(2) /// }}} {{{id=78| type(_) /// }}} {{{id=80| a,b = g(100) /// }}} {{{id=75| a /// }}} {{{id=81| b /// }}} {{{id=83| /// }}}

You can also take variable number of arguments and keyword arguments in a function:

{{{id=84| def h(*args, **kwds): print type(args), args print type(kwds), kwds /// }}} {{{id=82| h(1,2,3,n=4) /// }}} {{{id=88| /// }}} {{{id=92| /// }}}

Let's use the yield function to make an generator for the Fibonacci numbers up to n:

{{{id=87| def fib_gen(n): if n < 1: return a = b = 1 yield b while b < n: yield b a, b = b, b+a /// }}} {{{id=86| for i in fib_gen(50): print i /// }}} {{{id=94| /// }}}