= ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
gamme
print(gamme[0])
print(gamme[1])
print(gamme[2])
do
re
mi
In the previous tutorial, we studied tests, which allow a computer to make decisions based on conditions specified in a program. We will now go even further in automating operations with the concept of loops. Loops will allow us to repeat an instruction several times without having to rewrite the same code each time.
To illustrate this idea, let’s imagine we want to display each element of a list. For now, we would do:
= ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
gamme
print(gamme[0])
print(gamme[1])
print(gamme[2])
do
re
mi
And so on. We can immediately see that such an operation would be impractical for a list containing hundreds of elements. Loops will solve this problem in an elegant and efficient manner.
The first type of loop we will look at is the for
loop. A for
loop allows you to traverse the different elements contained in an object called an iterable, and perform operations with these elements. Iterable objects include all the sequential objects we have seen so far: strings, lists, tuples, etc.
Let’s illustrate how a for
loop works by solving the problem presented earlier.
for note in gamme:
print(note)
do
re
mi
fa
sol
la
si
Let’s analyze the structure of a for
loop:
The first line specifies a for
statement, and like any statement in Python ends with :
.
This is followed by a block of instructions, i.e., a series of operations (just one in our example) that will be executed at each iteration of the loop. This block is visible by its level of indentation, incremented by 1 compared to the statement. The block ends as soon as the indentation returns to its initial level.
As with conditional statements like if
/else
, indentation is crucial. If you forget it, Python returns an error.
for note in gamme:
print(note)
do
re
mi
fa
sol
la
si
Now let’s look in more detail at what the for
statement does. It defines an iteration variable (called note
in our example), which will traverse the elements of the iterator specified after the in
(the list gamme
in our example). The syntax of a loop in Python lends itself well to a literal description; in our case: “for each note in the list gamme, print the note.”
Note that a loop defines a variable without needing the traditional variable = value
assignment syntax. Furthermore, this variable is not deleted once the loop is finished; it then takes the value of the last element of the iterator.
note
'si'
The iterator does not necessarily have to be a list; it can be any iterable object. This includes all the sequential objects we have seen.
for char in "YMCA":
print(char)
print() # Newline
= (1, 2, 3, 4, 5)
t for i in t:
print(i*9)
Y
M
C
A
9
18
27
36
45
However, the class of iterable objects is much larger than just sequential objects. For example, you can iterate over the keys of a dictionary, even though we saw in a previous tutorial that it is not a sequential object, since there is no notion of order in a dictionary.
= {'coffee': '500g', 'milk': '1.5L', 'cereal': '1kg'}
inventaire for key in inventaire:
print(key)
print(inventaire[key])
print() # Newline
coffee
500g
milk
1.5L
cereal
1kg
range
functionIn programming, it is common to want to iterate over a series of integers. Instead of specifying this series in a list, which is not very practical if the series is long, we use the range(n)
function. This creates an iterable object that contains all the integers between 0 and n-1, and can be used within a loop.
For example, let’s see how we can very simply display a multiplication table using this function.
= 9
table
for i in range(11):
print(i, i*9)
0 0
1 9
2 18
3 27
4 36
5 45
6 54
7 63
8 72
9 81
10 90
We have seen that a for
loop works by iterating over the elements of an iterable. However, in the case of a sequential object like a list, we may sometimes want to iterate over the indices of the object to manipulate both the indices and the elements contained in the object. In this case, the range
function can be used in combination with the len
function to create an iterable object that contains exactly the indices of the initial list.
= ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
gamme
for i in range(len(gamme)):
print("The note number " + str(i) + " in the C major scale is " + gamme[i])
The note number 0 in the C major scale is do
The note number 1 in the C major scale is re
The note number 2 in the C major scale is mi
The note number 3 in the C major scale is fa
The note number 4 in the C major scale is sol
The note number 5 in the C major scale is la
The note number 6 in the C major scale is si
Since this need is frequent but the code above is not very readable, there is a built-in Python function called enumerate
that allows iterating over both objects and indices. It is therefore preferable to use this syntax, which is clearer and helps avoid some errors.
The enumerate
function applied to an iterable object returns a new iterable object that contains all the pairs (index, element)
in the object, in the form of tuples. Since it is a special type of object – a generator, which we will see in a more advanced tutorial – you need to apply the list
function to display its content.
list(enumerate(gamme))
[(0, 'do'), (1, 're'), (2, 'mi'), (3, 'fa'), (4, 'sol'), (5, 'la'), (6, 'si')]
Let’s see how to rewrite the previous loop with this new syntax.
for i, note in enumerate(gamme):
print("The note number " + str(i) + " in the C major scale is " + note)
The note number 0 in the C major scale is do
The note number 1 in the C major scale is re
The note number 2 in the C major scale is mi
The note number 3 in the C major scale is fa
The note number 4 in the C major scale is sol
The note number 5 in the C major scale is la
The note number 6 in the C major scale is si
NB: To assign variables in the if
statement, we used a handy technique we had already mentioned in an exercise in the tutorial on lists and tuples: tuple unpacking. Let’s illustrate it with an example:
= (1, 2, 3)
t = t
a, b, c print(a)
print(b)
print(c)
1
2
3
while
loops provide an alternative way to specify repetitive procedures. The idea is no longer to iterate over a fixed number of objects, but to iterate as long as a condition (logical test) is met.
= 1
i while i <= 5:
print(i)
= i + 1 i
1
2
3
4
5
The main difference from the for
loop is the statement: it is now a while
statement, followed by a condition (test), and like any statement, ends with :
.
The principle is the same for the rest: the while
statement is followed by a block of instructions, indented by one level, which is executed sequentially at each iteration of the loop.
An essential difference between while
loops and for
loops lies in the stopping criterion. In a for
loop, this criterion is clear: the loop iterates over the elements of an iterable object, necessarily of finite size. The loop stops when each element of the iterable has been traversed.
In a while
loop, on the other hand, the stopping criterion is given by a logical condition, so the user must set the stopping criterion. In the example, for the loop to stop, the condition i <= 5
must become False
, meaning i
must become strictly greater than 5. We ensured this by initializing i
to 1 before the loop starts, and then incrementing i
by one unit at each iteration.
What happens if we forget to increment i
? The stopping criterion is never reached, so the loop is infinite, and we must use the “Stop” button (black square) in Jupyter to stop the running program. Let’s verify this by incrementing the wrong variable.
= 1
i = 1
j while i <= 5:
= j + 1 j
Therefore, when we suspect that a while
loop is taking too long to run, we must consider the possibility that we have fallen into an infinite loop, and ensure that the stopping criterion is reachable.
break
statementAn alternative way to specify a stopping criterion is to use the break
statement. When this statement is reached and executed, the loop is immediately interrupted.
Let’s illustrate its operation with an example. The first line creates an infinite loop because, by definition, True
is always evaluated as True
. The program then asks the user to type a name, and does so indefinitely until the user types the expected name. Only then is the break
statement reached, and the loop stops. The message “Welcome print
is not included in the loop.
= "Romain"
your_name
while True:
print("Please enter your name.")
= input()
name if name == your_name:
break
print("Welcome " + your_name)
It is important to note that a break
statement only terminates the loop of the directly superior level. In the case of a multi-level loop, it is entirely possible for operations to continue even when a break
statement has been reached.
Let’s illustrate this principle with an example.
= 0
i while i <= 5:
for j in range(5):
if j == 2:
print("Break.")
break
+= 1 i
File <tokenize>:7 print("Break.") ^ IndentationError: unindent does not match any outer indentation level
At each iteration of the while
loop, a for
loop is launched, which reaches a break
statement at the third iteration (when j
is 2). This stops the for
loop, but not the while
loop, which executes its subsequent instructions (incrementing i
by one unit) before proceeding to the next iteration.
continue
statementThe continue
statement allows you to skip to the next iteration of the loop.
Let’s enhance the previous example to illustrate its operation. As long as a different name than the expected one is entered, the continue
statement is evaluated, and the program continues to ask for a name. When the correct name is entered, the program asks the user to enter a password. If the password is the expected one, the break
statement is reached and executed, and the loop stops. If the password is incorrect, however, the loop restarts at the beginning of the execution block, so you need to enter a name again before the password.
= ""
your_name
while True:
print("Please enter your name.")
= input()
name if name != your_name:
continue
print("Please enter your password.")
= input()
password if password == "insee2021":
break
print("Welcome " + your_name)
NB: The code above is only for example purposes. As we will see in a future tutorial on best coding practices, you should never write secrets (passwords, tokens, etc.) in plain text in your code.
1/ How does a for
loop work?
2/ Does the iteration variable defined in a for
loop persist in memory once the loop is finished?
3/ What does the range
function do? Why is it particularly useful in for
loops?
4/ What does the enumerate
function do? Why is it particularly useful in for
loops?
5/ How does a while
loop work?
6/ When does a while
loop stop? How does this differ from for
loops?
7/ What does the break
statement do?
8/ What does the continue
statement do?
1/ A for
loop defines an iteration variable that will traverse each element of an iterable object. At each iteration, a series of instructions is executed.
2/ Yes, and its final value is equal to the last value of the iterable object.
3/ The range(n)
function creates an iterable object that contains all integers between 0 and n-1. It is widely used as an iterable in for
loops because it allows iterating over a sequence of integers without having to manually put them in a list.
4/ The enumerate
function applied to an iterable object returns a new iterable object that contains all pairs (index, element) associated with the initial object, in the form of tuples. In the context of a for
loop, it allows iterating over both the elements of an iterable and their positions.
5/ A while
loop executes a series of instructions repeatedly as long as the specified logical condition evaluates to True.
6/ A while
loop stops as soon as the specified logical condition evaluates to False. If this never happens, a while
loop can be infinite. In contrast, a for
loop can be very long but never infinite, as it stops as soon as it finishes traversing the object.
7/ The break
statement forces the loop of the directly superior level to terminate.
8/ The continue
statement forces the loop of the directly superior level to skip to the next iteration.
while
loopsTry to predict what the following while
loops will produce, and check your results.
# 1.
= 0
i while i <= 10:
print(i)
# 2.
= 1
a while (a < 10):
+= 1
a if a == 5:
break
print("Stopping condition reached.")
# 3.
while False:
print("hello world")
# 4.
while True:
print("hello world")
break
# 5.
while 5 >= 3:
continue
print("hello world")
# Test your answer in this cell
i
is never incremented, so the condition is always true. 0 will print infinitely.a
is 5. However, the print statement is misindented, so it will print 3 times instead of 1.False
evaluates to False
, so the loop does not execute at all. No output.True
evaluates to True
, so the loop is theoretically infinite, but there is a break. Thus, there will be only one iteration, resulting in one “hello world” print.5 >= 3
evaluates to True
, so the loop is infinite. The continue statement is executed at each iteration before the print can execute. The loop runs infinitely, but with no output.Source: python.sdv.univ-paris-diderot.fr
To visualize the importance of indentation in instruction blocks, try to predict what the following two programs will return. Which one has the expected effect?
= [4, 5, 6]
numbers for num in numbers:
if num == 5:
print("The test is true")
print(f"because the variable num is {num}")
The test is true
because the variable num is 5
= [4, 5, 6]
numbers for num in numbers:
if num == 5:
print("The test is true")
print(f"because the variable num is {num}")
because the variable num is 4
The test is true
because the variable num is 5
because the variable num is 6
# Test your answer in this cell
The first program is correct. In the second, the second print
is not correctly indented. As a result, it executes at each iteration and not just when num == 5
.
for
loop to a while
loopRewrite the following for
loop using a while
loop.
= ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
gamme
for i, note in enumerate(gamme):
print("The note number " + str(i) + " in the C major scale is " + note)
The note number 0 in the C major scale is do
The note number 1 in the C major scale is re
The note number 2 in the C major scale is mi
The note number 3 in the C major scale is fa
The note number 4 in the C major scale is sol
The note number 5 in the C major scale is la
The note number 6 in the C major scale is si
# Test your answer in this cell
= ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
gamme
= 0
i while i <= (len(gamme) - 1):
# Subtract 1 from the length of `gamme` because the max index is 6
print("The note number " + str(i) + " in the C major scale is " + gamme[i])
+= 1 i
The note number 0 in the C major scale is do
The note number 1 in the C major scale is re
The note number 2 in the C major scale is mi
The note number 3 in the C major scale is fa
The note number 4 in the C major scale is sol
The note number 5 in the C major scale is la
The note number 6 in the C major scale is si
Given a target integer target_num
and a list of integers l
as defined in the following cell. Using a for
loop and the enumerate
function:
Check if the target integer is present in the list l
.
If yes, display the message ‘The number target_num
is at position i
in the list’, and end the loop.
= 78
target_num
= [12, 98, 65, 39, 78, 55, 119, 27, 33] l
# Test your answer in this cell
= 78
target_num
= [12, 98, 65, 39, 78, 55, 119, 27, 33]
l
for i, n in enumerate(l):
if n == target_num:
print("The number " + str(n) + " is at position " + str(i) + " in the list.")
break
# NB: more efficient version without loop
if target_num in l:
= l.index(target_num)
pos print("The number " + str(target_num) + " is at position " + str(pos) + " in the list.")
The number 78 is at position 4 in the list.
The number 78 is at position 4 in the list.
The Fibonacci sequence is defined as follows:
The first two numbers are 0 and 1
Each subsequent number in the sequence is obtained by adding the two preceding numbers
Write a program to calculate the first \(n\) terms of the sequence using a for
loop.
# Test your answer in this cell
= 20
n_terms = 0
num1 = 1
num2
for i in range(n_terms):
print(num1)
= num1 + num2
num3 = num2
num1 =
num2
num3
File <tokenize>:11 num3 ^ IndentationError: unindent does not match any outer indentation level
Using two nested for
loops, build a dictionary tables
that allows generating multiplication tables up to the table of 12. Query your dictionary to check its accuracy.
Here are some examples of queries your dictionary should return:
tables[2][3] -> 6
tables[9][5] -> 45
tables[12][7] -> 84
# Test your answer in this cell
= {}
tables
for i in range(13):
= {}
tables[i] for j in range(13):
= i*j
tables[i][j]
print(tables[2][3])
print(tables[9][5])
print(tables[12][7])
6
45
84
Calculate the minimum and maximum of the following series of values without using Python’s min
and max
functions.
x = [8, 18, 6, 0, 15, 17.5, 9, 1]
# Test your answer in this cell
= [8, 18, 6, 0, 15, 17.5, 9, 1]
x
= x[0]
current_min = x[0]
current_max for n in x[1:]:
if n <= current_min:
= n
current_min if n >= current_max:
= n
current_max
print(current_min == min(x))
print(current_max == max(x))
True
True
Calculate the mean and variance of the following series of values without using pre-coded functions:
x = [8, 18, 6, 0, 15, 17.5, 9, 1]
To recall, the formulas are:
mean: \[\bar{x} = {\frac {1}{n}}\sum_{i=1}^{n}x_{i}\]
variance: \[\sigma^2 = {\frac {1}{n}}\sum_{i=1}^{n} (x_{i}-\bar{x})^2\]
NB:
n to the power of k is written in Python as n**k
in practice, you should never try to recode such functions yourself, but use functions from suitable packages like numpy
.
# Test your answer in this cell
= [8, 18, 6, 0, 15, 17.5, 9, 1]
x = len(x)
n
= 0
sum_mean for x_i in x:
+= x_i
sum_mean = sum_mean / n
mean
= 0
sum_var for x_i in x:
+= (x_i - mean)**2
sum_var = sum_var / n
variance
print(mean)
print(variance)
# Verification with numpy package functions
import numpy as np
print(np.mean(x))
print(np.var(x))
9.3125
42.93359375
9.3125
42.93359375
range
functionWe saw earlier the basic use of the range
function: range(n)
creates an iterable object that contains all integers from 0 to n-1. The possible uses of this function are, however, more comprehensive and sometimes useful for specific problems.
The complete syntax of the function is range(start, stop, step)
where:
start
is the integer at which the sequence of integers starts
stop
is the integer before which the sequence of integers ends
step
is the step, i.e., the value of the increment between each integer in the sequence.
Only the stop
parameter is mandatory, which is used when calling range(n)
.
Using the range
function, display:
All integers from 0 to 10 (10 excluded)
All integers from 10 to 20 (20 included)
All even numbers between 30 and 40 (40 included)
All multiples of 10 between 1 and 100 (100 excluded)
All integers from 10 to 20 (20 included), in reverse order (from 20 to 10)
# Test your answer in this cell
print(list(range(10)))
print(list(range(10, 21)))
print(list(range(30, 41, 2)))
print(list(range(10, 100, 10)))
print(list(range(20, 9, -1)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[30, 32, 34, 36, 38, 40]
[10, 20, 30, 40, 50, 60, 70, 80, 90]
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10]
In the previous tutorial, we coded a game of “The Price is Right”. But it was somewhat limited because you had to rerun the code at each stage of the game. Using loops, rewrite the game to be fully automatic.
Game rules reminder:
Using input
and the if
, elif
, and else
statements, code the following program:
Ask the user for a value, which will be stored in a variable p
If p
is strictly less than $15, print (using the print
function) the message “too low!”.
If p
is strictly greater than $15, print the message “too high!”.
If p
equals $15, print the message “spot on!”
Note, input
returns a string by default. Therefore, you need to convert the value of p
to an integer (using the int
function) for the game to work.
# Test your answer in this cell
= 15
right_price
while True:
print("Propose a number between 1 and 50.")
= input()
p = int(p)
p if p < right_price:
print("too low!")
elif p > right_price:
print("too high!")
else:
break
print("spot on!")
Propose a number between 1 and 50.
--------------------------------------------------------------------------- StdinNotImplementedError Traceback (most recent call last) Cell In[64], line 5 3 while True: 4 print("Propose a number between 1 and 50.") ----> 5 p = input() 6 p = int(p) 7 if p < right_price: File /opt/hostedtoolcache/Python/3.10.15/x64/lib/python3.10/site-packages/ipykernel/kernelbase.py:1281, in Kernel.raw_input(self, prompt) 1279 if not self._allow_stdin: 1280 msg = "raw_input was called, but this frontend does not support input requests." -> 1281 raise StdinNotImplementedError(msg) 1282 return self._input_request( 1283 str(prompt), 1284 self._parent_ident["shell"], 1285 self.get_parent("shell"), 1286 password=False, 1287 ) StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.