Control structures#
Learning goals
After finishing this chapter, you are expected to
use
if
,elif
, andelse
write
while
loopswrite
for
loops
Conditional statements with if
#
Now that you are able to write and run scripts in VS Code, it is time to do some more interesting programming. So far, your scripts have been quite predictable. They are a series of statements that are executed from top to bottom, i.e., sequential execution. One nice feature of almost all programming languages is that they allow the use of control structures that direct the execution of your program. One of the most commonly used control structures is the conditional statement if
. An if
statement looks like this:
if <expr>:
<statement>
Here, <expr>
is a boolean expression, i.e., something that takes on the value True
or False
. The <statement>
is a valid Python statement, something that will be executed if <expr>
evaluates to True
. The colon :
is part of the Python syntax and should always be placed after the boolean expression. Further, note that there is some whitespace in front of the <statement>
. This is called indentation and is also part of the Python syntax. Python uses four spaces as indentation. You usually don’t have to care of this yourself: the interpreter and any IDE that knows that you’re programming in Python will help you automatically use that indentation when necessary.
To get a better feeling about the behavior of the if
-statement, take a good look at the following code examples. Note that the interpreter only prints yes
if the <expr>
is True
. Otherwise, nothing happens. Also, note that if y
gets evaluated to True
. This is so because Python evaluates any integer value larger that is not zero as True
(we have also seen this in the previous chapter).
x = 0
y = 5
if x < y: # True
print('yes')
yes
if y < x: # False
print('yes')
if x: # False
print('yes')
if y: # True
print('yes')
yes
In the previous chapter, you have used the and
, or
and not
logical operators that evaluate to a boolean. You can also use these in the expression of your if
statement, as in the examples below.
if x or y: # True
print('yes')
yes
if x and y: # False
print('yes')
if not x: # True
print('yes')
yes
Blocks#
The <statement>
that follows an if
condition in Python does not necessarily have to be just one line of code. In fact, you can add a block or suite of statements after your if
condition. As long as you stay at the same indentation level, these will be jointly executed with the first statement. For example, based on the cases above, we could have the following piece of code:
if y:
print('y')
print('is a non-zero integer')
print('so I will print')
print('yes')
y
is a non-zero integer
so I will print
yes
Here, all the print statements form a block of code at the same indentation level. Within a block, you can have additional if statements. For example, instead of writing if x and y:
as we did above, you could also write the following to get the exact same behavior. Notice that now we have added two levels of indentation.
if x:
if y:
print('yes')
Blocks can be nested to arbitrary depth, and depending on the expressions, some lines will be executed while others won’t.
Exercise 3.1
One of the lines in the following code is not executed. Which line is it?
if 'foo' in ['foo', 'bar', 'baz']:
print('Outer condition is true')
if 10 > 20:
print('Inner condition 1')
print('Between inner conditions')
if 10 < 20:
print('Inner condition 2')
print('End of outer condition')
print('After outer condition')
else
and elif
#
As you might expect, where there’s an if
there can also be an else
. This else
is an expression which is evaluated as the opposite of the if
expression. The statement following this expression is what gets executed if the expression following if
is evaluated to be False
.
For example, take the following piece of code. In this case, the expression following if
is obviously False
, so the statement following else
will be executed and ‘smaller’ will be printed.
if 10 > 20:
print('larger')
else:
print('smaller')
smaller
A third kind of expression is the elif
or ‘else if’ expression that can be used in case there are more than two possible outcomes. Following an if
expression, you can have any number of elif
expressions that you desire, potentially followed by an else
statement. Note that if the expression following if
is True
, none of the other expressions will actually be checked. Similarly, as soon as one of the elif
conditions is true, the other conditions will not be checked. The following provides an example of using if
, elif
and else
.
language = 'french'
if language == 'english':
print('hello')
elif language == 'dutch':
print('hallo')
elif language == 'french':
print('bonjour')
else:
print('unknown language')
bonjour
Exercise 3.2
In each of the following equations, evaluate the given code fragments. Investigate each of the fragments for the various starting values. Use Python to check your answer.
What is the value of
m
if
a)n = 7
b)n = 0
c)n = -7
?if n > 1: m = n + 2 else: m = n - 1
What is the value of
t
if
a)s = 1
b)s = 7
c)s = 57
d)s = 300
if s <= 1:
t = 2*s
elif s < 10:
t = 9 - s
elif s < 100:
t = s**2
else:
t = s
What is the value of
h
if
a)t = 50
b)t = 19
c)t = -6
d)t = 0
if t >= 24:
h = 3*t + 1
elif t < 9:
h = t**2/3 - 2*t
else:
h = -t
What is the value of
y
if
a)x = -1
b)x = 5
c)x = 30
d)x = 56
if 0 < x < 7:
y = 4 * x
elif 7 < x < 55:
y = -10 * x
else:
y = 333
Exercise 3.3
A bank will offer a customer a loan if they are 21 or over and have an annual income of at least €21000. Write a Python script that contains the customer’s age and income in a dictionary. Depending on the age and income, one of the following lines should be printed (using the print
function):
‘We are able to offer you a loan.’
‘Unfortunately at this time we are unable to offer you a loan.’
Verify your code by testing with
A 40-year old man with an annual income of €11000
A 18-year old woman with an annual income of €25000
A 30-year old woman with an annual income of €40000
A 15-year old boy with an annual income of €5000
Exercise 3.4
Write a Python script that asks the user for two numbers and prints ‘The first number can be divided by the second number’ or ‘The first number cannot be divided by the second number’, depending on which is the case.
Conditional expression
In addition to the syntax above, Python offers a compact way of writing binary if
/else
statements. This is called a conditional expression or ternary operator and means that the expression
if 10 > 20:
print('larger')
else:
print('smaller')
can also be written in one line of code as
print('larger') if 10 > 20 else print('smaller')
It can in some cases be useful two write expressions like this, for example when you want to compactly assign a value to a variable.
coat = 'raincoat' if raining else 'jacket'
while
loops#
Iteration control structures, loops, are used to repeat a block of statements until some condition is
met. Python supports two types of loops: the while
-loop and the for
-loop. A while loop executes some statement as long as a condition is True
. We call each time that the statement below while
is executed an ‘iteration’. As soon as the condition is False
the loop will stop iterating.
a = 1
while a < 10:
print(a)
a += 2
The animation below nicely visualizes how a while
loop works in this piece of code. As you can see, the while
statement is checked at the beginning of each iteration. If that is the case, the block below the while
statement is executed. If not, the loop ends.
You can use while
loops for situations in which you do not know beforehand how many iterations you need. For example, we can write a script that uses a while
loop to create the longest possible list of even numbers that together are less than 40.
even_sum = 0
n = 0
even_numbers = []
while even_sum < 40:
even_sum += n
even_numbers.append(n)
n += 2
print(even_sum)
print(even_numbers[:-1])
42
[0, 2, 4, 6, 8, 10]
If you look closely at this example, you can see that even_sum
is actually larger than 40. This is so because at the moment that even_sum < 40
became False
(and the loop stopped), the last number n
=12 had already been added to even_numbers
. Hence, we have to use slicing to exclude the last number in the print statement.
We could prevent this by using an if
expression and a break
statement. Once Python encounters a break
, it immediately exits whatever loop it is in. In this case, the code could be changed to the following.
even_sum = 0
n = 0
even_numbers = []
while even_sum < 40:
if even_sum + n >= 40: # Check if adding the current number n would let even_sum exceed 40
break # If that is the case, get out of the loop immediately
else: # If not, continue looping
even_sum += n
even_numbers.append(n)
n += 2
print(even_sum)
print(even_numbers)
30
[0, 2, 4, 6, 8, 10]
In addition to break
, Python also contains a continue
statement. If Python encounters a continue
statement, it stays in the loop, but ends the current iteration. In our example, imagine that (for some reason) we do not want to include a number n
if it can be divided by 6. Then we can add an elif
statement to check this condition and skip the current iteration if the condition is met.
even_sum = 0
n = 0
even_numbers = []
while even_sum < 40:
if even_sum + n >= 40: # Check if adding the current number n would let odd_sum exceed 40
break # If that is the case, get out of the loop immediately
elif n % 6 == 0: # If the number n can be divided by 6
n += 2 # Increment the number
continue # Move on to next iteration
else: # If neither condition is met, continue looping
even_sum += n
even_numbers.append(n)
n += 2
print(even_sum)
print(even_numbers)
38
[2, 4, 8, 10, 14]
Infinite loops
A while
loop will continue running as long as its condition is True
. That means that it’s also possible to make an infinite loop that causes your code to get stuck. For example, the following code will run forever if you don’t stop it.
while True:
print('Running')
If you make such a loop, always make sure that there is also a break
statement inside (in combination with an if
) so you an actually exit the loop. If you accidentally do end up in an infinite loop, you can in most terminals use Ctrl + c to shut down your script.
Exercise 3.5
Write a script that determines the largest integer \(n\) for which \(1^3 + 2^3 + \cdots + n^3\) is less than 2000.
Exercise 3.6
Write a guessing game where the user has to guess a secret number. After every guess the program tells the user whether their number was too large or too small. At the end of the game, the number of tries needed by the user should be printed. If a user adds the same number twice in a row, it counts as one try.
Start your script with the following code to define the secret number:
import random
secret_number = random.randint(0, 50)
# The rest of your code goes here
for
loops#
In contrast to a while
-loop, for which the number of iterations is not defined, in a for
-loop the number of iterations is fixed upon entering the loop. The standard for-loop has general syntax
for item in <sequence>:
do something
Here, <sequence>
can be a list, set, tuple, dictionary, or string. For example, we can print all elements in the list [1, 2, 3, 5, 8]
as follows
for item in [1, 2, 3, 5, 8]:
print(item)
1
2
3
5
8
The for-loop iterates over something which we call an iterable: an object that is able to return its items one-by-one until no more items remain. For example, if we want to print ‘Hello world’ five times, we can make a list with five items (here digits) and iterate over that list.
for item in [1, 2, 3, 4, 5]:
print('Hello world')
Hello world
Hello world
Hello world
Hello world
Hello world
Note that in the example above, we actually don’t do anything with the items in the list. We have here used integers in ascending order, but basically any item of any type will do. In contrast to other programming languages, Python does not use these integers as indices unless you want it to do so. We do have to give a name to the variable that holds the value coming from the list, but we could also use the ‘throwaway’ variable name _
. To illustrate this, the previous result could also have been obtained with strings in a list.
for _ in ['person', 'woman', 'man', 'camera', 'tv']:
print('Hello world')
Hello world
Hello world
Hello world
Hello world
Hello world
Now let’s say that we want to do something a 1000 times. For example, add all integers between 0 and 1000. You can imagine it would be very cumbersome to write out a list with 1000 integers to iterate over. Luckily, the built-in range(start, stop, step)
function in Python returns an iterable that provides numbers from start
to stop
with an interval of step
. Now, to print ‘Hello world’ 5 times, we simply use.
for _ in range(0, 5, 1):
print('Hello world')
Hello world
Hello world
Hello world
Hello world
Hello world
The arguments of the range
function work very similar to slicing that you have seen for lists and tuples. The function returns integers up to but not including the stop
argument. Moreover, step sizes can be negative. Take a look at the following examples.
for digit in range(0, 5, 1):
print(digit)
print('---')
for digit in range(1, 9, 2):
print(digit)
print('---')
for digit in range(9, 2, -1):
print(digit)
0
1
2
3
4
---
1
3
5
7
---
9
8
7
6
5
4
3
As mentioned above, your for
loop can iterate over lists, tuples, sets, dictionaries, and strings. For example, we can loop over the letters in a string.
some_string = 'coffee'
for letter in some_string:
print(letter)
c
o
f
f
e
e
break
and continue
Just like in a while
loop, you can use break
and continue
to exit the loop or skip iterations in a for
loop.
Exercise 3.7
Write short scripts using loop constructions for the following tasks.
Determine the sum of the first 50 squared numbers with a loop.
Create a script with just one loop that calculates the sum of all entries of a vector \(x\) and also the vector of running sums (as a list). The running sum of a vector \(x\) of \(n\) entries is the vector of \(n\) entries defined as \([x_0, x_0+x_1, x_0+x_1+x_2, \cdots, x_0+x_1+\ldots+x_n]\). Test your code for x = \([1, 9, 1, 0, 4]\).
Nested loops#
Just like we can nest conditional statements in blocks, we can also nest loops. For example, we can generate a multiplication table for numbers 1 to 5 with two nested loops.
for i in range(1, 6):
row = []
for j in range(1, 6):
row.append(i*j)
print(row)
[1, 2, 3, 4, 5]
[2, 4, 6, 8, 10]
[3, 6, 9, 12, 15]
[4, 8, 12, 16, 20]
[5, 10, 15, 20, 25]
There are no restrictions on kinds of loops that you nest: a for
loop can contain a while
loop and vice versa. Moreover, there are no restrictions on the number of loops that you nest (or the depth). You can, for example, nest three loops as follows.
for i in range(3):
j = 0
while j < 7:
for k in range(2):
print(i, j, k)
j = j + 2
0 0 0
0 2 1
0 4 0
0 6 1
1 0 0
1 2 1
1 4 0
1 6 1
2 0 0
2 2 1
2 4 0
2 6 1
Simultaneously looping over two sequences#
Sometimes you might want to loop over two sequences at the same time. An easy example is pairwise multiplication of two vectors: the aim is to compute a new vector in which each element is the product of the elements in the two input item at the same index. For this, you can use the zip
function that you have seen before and that acts like a zipper conjoining two lists. See below for an example
vector_a = [3, 6, 5] # Define an input vector as a list
vector_b = [2, 4, 8] # Define a second input vector
vector_c = [] # Define an output vector
for elem_a, elem_b in zip(vector_a, vector_b): # Jointly iterate over the two input vectors
vector_c.append(elem_a * elem_b) # Append product of elements to output vector
print(vector_c)
[6, 24, 40]
Exercise 3.8
Write a script that does the following
ask the user for a number \(n\)
give the user the choice between computing the sum and computing the product of \(1,\ldots,n\)
compute the desired result
print the result for the user
Exercise 3.9
Write a program that uses loops to compute Fibonacci numbers (as in Exercise 1.12). The scripts asks the user how many numbers should be computed. This can be any number, so your code should be flexible.