Loops and Functions
system:sage


<h1 style="text-align: center;">Loops and Functions</h1>
<p>For more verbose explanation of what's going on here, a good place to look is at the following section of the Python tutorial: <a title="http://docs.python.org/tutorial/controlflow.html" href="http://docs.python.org/tutorial/controlflow.html">http://docs.python.org/tutorial/controlflow.html</a></p>
<h2>While Loops</h2>
<p>While loops tend not to be used nearly as much as for loops in Python code.</p>

{{{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
///
}}}

<p>Note that the truth value expression in the <strong>while</strong> loop is evaluated using bool().</p>

{{{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|

///
}}}

<h2>For Loops</h2>
<p>&nbsp;</p>

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

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

{{{id=12|

///
}}}

<p>The <strong>range</strong> function is very useful when you want to generate arithmetic progressions to loop over.&nbsp; Note that the end point is never included:</p>

{{{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
///
}}}

<p>You can use the <strong>continue</strong> keyword to immediately go to the next item in the loop:</p>

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

{{{id=23|

///
}}}

<p>If you want to break out of the loop, use the <strong>break</strong> keyword:</p>

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

{{{id=7|

///
}}}

<p>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:</p>

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

{{{id=32|

///
}}}

<p>It's cleaner to use <strong>enumerate</strong> which provides the index as well as the value:</p>

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

{{{id=35|

///
}}}

<p>You could make something similary to the <strong>enumerate</strong> function by using <strong>zip</strong> to zip two lists together:</p>

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

{{{id=28|

///
}}}

<p>For loops work using Python's iterator protocol.&nbsp; This allows all sorts of different objects to be looped over.&nbsp; For example,</p>

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

<p>How does it work?</p>

{{{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__??
///
}}}

<p><strong>yield</strong> provides a very convient way to produce iterators.&nbsp; We'll see more about it in a bit.</p>

{{{id=25|

///
}}}

<h2>Functions</h2>

<p>Functions are defined using the <strong>def</strong> statement, and values are returned using the <strong>return</strong> keyword.</p>

{{{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|

///
}}}

<p>Functions are first class objects like any other.&nbsp; For example, they can be passed in as arguments to other functions.</p>

{{{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|

///
}}}

<p>You can give default values for arguments in functions:</p>

{{{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)
///
}}}

<p>You can return multiple things from a function:</p>

{{{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|

///
}}}

<p>You can also take variable number of arguments and keyword arguments in a function:</p>

{{{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|

///
}}}

<p>Let's use the <strong>yield</strong> function to make an generator for the Fibonacci numbers up to n:</p>

{{{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|

///
}}}