Python loops#
Loops are used when you need to run the same expression repeatedly for 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(f'x = {x:d}')
x = 1
x = 5
x = 6
x = 10
x = 20
for c in 'This is a string':
print(f"c = '{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(f'i = {i:d}')
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(f'i = {i:d}')
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(f'i = {i:d}')
i = 2
i = 4
i = 6
i = 8
And you can also go backwards:
for i in range(10, 0, -1):
print(f'i = {i:d}')
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 data and write code to calculate the average using a for
loop:
data = [15.0, 0.25, 3.5, 5.1, 21.16]
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(f'Average = {average:1.2f}')
Average = 9.00
Let’s compare this to the other way we have learned:
print(f'Average the other way = {sum(data) / N:1.2f}')
Average the other way = 9.00
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(f'Average = {average:1.2f}')
Average = 9.00
Questions#
Write a
for
loop that calculates the average of all thedata
elements that are greater than 5.
# Your code here
Write a
for
loop to calculate the second moment of thedata
, i.e., this expression:
# Your code here
Write a
for
loop that finds the maximum of thedata
.
# Your code here
The while
loop#
The while
loop is a bit more general than the for
loop as stopping depends on a boolean expression.
Its 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(f'i = {i:d}')
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(f'pi ~= {4 * a:1.12f}')
pi ~= 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(f'Current iteration n = {n:10d}, pi ~= {4 * a:1.12f}')
# and increase the counter
n += 1
print(f'pi ~= {4 * a:1.12f}')
Current iteration n = 0, pi ~= 4.000000000000
Current iteration n = 10000, pi ~= 3.141692643591
Current iteration n = 20000, pi ~= 3.141642651090
Current iteration n = 30000, pi ~= 3.141625985812
Current iteration n = 40000, pi ~= 3.141617652965
Current iteration n = 50000, pi ~= 3.141612653190
Current iteration n = 60000, pi ~= 3.141609319979
Current iteration n = 70000, pi ~= 3.141606939100
Current iteration n = 80000, pi ~= 3.141605153434
Current iteration n = 90000, pi ~= 3.141603764577
Current iteration n = 100000, pi ~= 3.141602653490
pi ~= 3.141602653490
We are going to end with a final modification: a convergence test. 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 can test for this condition using an if
statement.
But how can we stop the loop when this condition is met?
We can do this by using the break
command.
The break
command exits the loop immediately (note that it also works in for
loops).
Here we go:
max_iter = 10000000
epsilon = 1e-6
n = 0
a = 0.0
while n <= max_iter:
a_n = (-1) ** n / (2 * n + 1)
if abs(a_n) < epsilon:
print(f'*** Converged in {n+1:d} iterations! ***')
break
a += a_n
if n % 100000 == 0:
print(f'Current iteration n = {n:10d}, pi ~= {4 * a:1.12f}')
n += 1
if n == max_iter + 1:
print(f'*** Stopped when maximum number of iterations ({max_iter:d}) were reached! ***')
print(f'pi ~= {4 * a:1.12f}')
Current iteration n = 0, pi ~= 4.000000000000
Current iteration n = 100000, pi ~= 3.141602653490
Current iteration n = 200000, pi ~= 3.141597653565
Current iteration n = 300000, pi ~= 3.141595986912
Current iteration n = 400000, pi ~= 3.141595153583
*** Converged in 500001 iterations! ***
pi ~= 3.141590653590
Questions#
Modify the code above so that you estimate the series:
which converges to \(2\).