Python loops
Contents
Python loops¶
Loops are used when you need to run the same expression of similar data.
There are two kinds of loops in Python: for
loops and while
loops.
for
loops¶
The syntax of for
loops is as follows:
for <variable> in <collection>:
# run an expression potentially using <variable>
# run another expression ...
The idea is that <collection>
is an iterable object like a tuple
or a list
and that <variable>
takes sequentially each one of the values in that iterable object.
Here are a few examples:
for x in (1, 5, 6, 10, 20):
print('x = {0:d}'.format(x))
x = 1
x = 5
x = 6
x = 10
x = 20
for x in [1, 5, 6, 10, 20]:
print('x = {0:d}'.format(x))
x = 1
x = 5
x = 6
x = 10
x = 20
for c in 'This is a string':
print('c = \'{0:s}\''.format(c))
c = 'T'
c = 'h'
c = 'i'
c = 's'
c = ' '
c = 'i'
c = 's'
c = ' '
c = 'a'
c = ' '
c = 's'
c = 't'
c = 'r'
c = 'i'
c = 'n'
c = 'g'
Very often, we want to loop over all values from 0 to a given number.
We can do this with range
:
for i in range(10):
print('i = {0:d}'.format(i))
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
You don’t have to start at 0:
for i in range(2, 10):
print('i = {0:d}'.format(i))
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
And you can skip numbers:
for i in range(2, 10, 2):
print('i = {0:d}'.format(i))
i = 2
i = 4
i = 6
i = 8
And you can also go backwards:
for i in range(10, 0, -1):
print('i = {0:d}'.format(i))
i = 10
i = 9
i = 8
i = 7
i = 6
i = 5
i = 4
i = 3
i = 2
i = 1
Let’s now create some random data and write code to calculate the average:
data = [0.16295757, 0.06804887, 0.76082389, 0.39089033, 0.63845432,
0.12555193, 0.98251807, 0.38759292, 0.75819177, 0.63329008,
0.94419572, 0.95363126, 0.60753037, 0.55727347, 0.55989237,
0.2482676 , 0.13208943, 0.25090889, 0.7912593 , 0.30045856]
Recall that the average of \(N\) numbers \(x_1, x_2,\dots,x_N\) is:
Here is how we can code this with a for loop:
# The number of observations
N = len(data)
# A variable that stores the sum of all the x's as we go through
# the data
s = 0.0
# The loop
for i in range(len(data)):
x = data[i]
# This is just a shortcut for s = s + x
s += x
average = s / N
print('Average = {0:1.2f}'.format(average))
Average = 0.51
Let’s compare this to the other way we have learned:
print('Average the other way = {0:1.2f}'.format(sum(data) / N))
Average the other way = 0.51
Okay. It worked fine. Here is another way to do the same thing. Instead of using an index, we can directly go over each element in the list like this:
s = 0.0
for x in data:
s += x
average = s / N
print('Average = {0:1.2f}'.format(average))
Average = 0.51
Questions¶
Write a code block that calculates the average of all the
data
elements that are greater than 0.5.
# Your code here
Write a for loop to calculate the second moment of the
data
, i.e., this expression:
# Your code here
In the code block provided below, write a for loop that finds the maximum of the
data
.
# Your code here
while
loops¶
While loops are a bit more general than for loops as stopping depends on a boolean expression. Their syntax is like this:
while <boolean_expression>:
# Some expressions to execute
# Some other epxression to execute
Let’s see some examples of this:
i = 0
while i < 10:
print('i = {0:d}'.format(i))
i += 1
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
Let’s do a more mathematical example. We are going to write code that calculates the sum of a series to a given tolerance. That is, given a sequence of numbers: \(a_1, a_2, \dots,\), we will write code that approximates:
To be specific, we are going to sum this series:
and use it to approximate \(\pi\). This is known as the Leibniz formula. In terms of the \(\alpha_n\) notation above, the formula is:
Here is our first attempt:
# The maximum number of iterations you are willing to do:
max_iter = 100000
# The result
a = 0.0
# Start a counter
n = 0
# Start the loop
while n <= max_iter:
# Compute the new term
a_n = (-1) ** n / (2 * n + 1)
# Add it to the sum
a += a_n
# and increase the counter
n += 1
print('4 * a ~= {0:1.12f}'.format(4 * a))
4 * a ~= 3.141602653490
Let’s now make our code print something every few iterations (say every 10,000 iterations).
# The maximum number of iterations you are willing to do:
max_iter = 100000
# The result
a = 0.0
# Start a counter
n = 0
# Start the loop
while n <= max_iter:
# Compute the new term
a_n = (-1) ** n / (2 * n + 1)
# Add it to the sum
a += a_n
# Print something about the current iteration
if n % 10000 == 0:
print('Current iteration n = {0:10d}, pi estimate so far: {1:1.12f}'.format(n, 4 * a))
# and increase the counter
n += 1
print('')
print('4 * a ~= {0:1.12f}'.format(4 * a))
Current iteration n = 0, pi estimate so far: 4.000000000000
Current iteration n = 10000, pi estimate so far: 3.141692643591
Current iteration n = 20000, pi estimate so far: 3.141642651090
Current iteration n = 30000, pi estimate so far: 3.141625985812
Current iteration n = 40000, pi estimate so far: 3.141617652965
Current iteration n = 50000, pi estimate so far: 3.141612653190
Current iteration n = 60000, pi estimate so far: 3.141609319979
Current iteration n = 70000, pi estimate so far: 3.141606939100
Current iteration n = 80000, pi estimate so far: 3.141605153434
Current iteration n = 90000, pi estimate so far: 3.141603764577
Current iteration n = 100000, pi estimate so far: 3.141602653490
4 * a ~= 3.141602653490
Now, let’s not run forever. We are going to modify the code so that it loops over \(n\) until \(|a_{n+1}| < \epsilon\), where \(\epsilon\) is a small positive number typically called a tolerance. We are going to use the keyword break
to achieve this.
break
is a command to exit the loop (note that it also works in for
loops).
Here we go:
# The maximum number of iterations you are willing to do.
# You always add something like this to avoid looping forever
max_iter = 10000000
# The tolerance you wish to reach:
epsilon = 1e-6
# The result
a = 0.0
# Start a counter
n = 0
# Start the loop
while n <= max_iter:
# Compute the new term
a_n = (-1) ** n / (2 * n + 1)
# Check if the absolute value of the new term is smaller than the tolerance
if abs(a_n) < epsilon:
# If it is indeed smaller, exit the loop
# you do this with the command
print('*** Converged in {0:d} iterations! ***'.format(n+1))
break
# Otherwise we just add the new term to our running sum
a += a_n
# Print something about the current iteration
if n % 100000 == 0:
print('Current iteration n = {0:10d}, sum so far: {1:1.12f}'.format(n, 4 * a))
# and increase the counter
n += 1
if n == max_iter + 1:
print('*** Stopped when maximum number of iterations ({0:d}) were reached! ***'.format(max_iter))
print('4 * a ~= {0:1.12f}'.format(4 * a))
Current iteration n = 0, sum so far: 4.000000000000
Current iteration n = 100000, sum so far: 3.141602653490
Current iteration n = 200000, sum so far: 3.141597653565
Current iteration n = 300000, sum so far: 3.141595986912
Current iteration n = 400000, sum so far: 3.141595153583
*** Converged in 500001 iterations! ***
4 * a ~= 3.141590653590
Questions¶
Modify the code above so that you estimate the series:
which converges to \(2\).