Course: Deep Learning for Solving and Estimating Dynamic Models in Economics and Finance
Script reference: Front matter and Appendix~E — for / while loops, range, enumerate
Notebook role: primer (pre-course self-study; skip if you write Python every day)
Author: Simon Scheidegger
Python Basics 6: 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]# 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
dataelements that are greater than 0.5.
# Your code hereWrite a for loop to calculate the second moment of the
data, i.e., this expression:
# Your code hereIn the code block provided below, write a for loop that finds the maximum of the
data.
# Your code herewhile 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 executeLet’s see some examples of this:
i = 0
while i < 10:
print('i = {0:d}'.format(i))
i += 1i = 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: , we will write code that approximates:
To be specific, we are going to sum this series:
and use it to approximate . This is known as the Leibniz formula. In terms of the 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}, sum so far: {1:1.12f}'.format(n, a))
# and increase the counter
n += 1
print('')
print('4 * a ~= {0:1.12f}'.format(4 * a))Current iteration n = 0, sum so far: 1.000000000000
Current iteration n = 10000, sum so far: 0.785423160898
Current iteration n = 20000, sum so far: 0.785410662772
Current iteration n = 30000, sum so far: 0.785406496453
Current iteration n = 40000, sum so far: 0.785404413241
Current iteration n = 50000, sum so far: 0.785403163297
Current iteration n = 60000, sum so far: 0.785402329995
Current iteration n = 70000, sum so far: 0.785401734775
Current iteration n = 80000, sum so far: 0.785401288358
Current iteration n = 90000, sum so far: 0.785400941144
Current iteration n = 100000, sum so far: 0.785400663372
4 * a ~= 3.141602653490
Now, let’s not run forever. We are going to modify the code so that it loops over until , where 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 = 1000000
# The tolerance you wish to reach:
epsilon = 1e-4
# 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('Current iteration n = {0:10d}, sum so far: {1:1.12f}'.format(n, a))
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 % 1000 == 0:
print('Current iteration n = {0:10d}, sum so far: {1:1.12f}'.format(n, 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: 1.000000000000
Current iteration n = 1000, sum so far: 0.785647913585
Current iteration n = 2000, sum so far: 0.785523100921
Current iteration n = 3000, sum so far: 0.785481468960
Current iteration n = 4000, sum so far: 0.785460647775
Current iteration n = 5000, sum so far: 0.785348163398
*** Converged in 5001 iterations! ***
4 * a ~= 3.141392653592