Table of Contents
Introduction
We know that Python statements are executed sequentially. That is, the first statement in a program is executed first, followed by the second and so on. There may be a situation when you need to execute a block of code several times. A loop statement allows us to execute a code block multiple times without repeating the code in the program.
The for Loop
The for
loop in Python is used to iterate over iterable objects like list, tuple, string, sets and dictionaries. The syntax of the for
loop is as follows:
Syntax
Thefor
loop.
1for item in sequence:
2 loop body
The variable item
is called the loop variable. It changes for each iteration of the loop. The loop continues until we reach the last item in the sequence. Notice that the body of for loop is indented with a tab.
Example
Thefor
loop.
1list1 = [2,4,6,8,10]
2for item in list1:
3 print(item)
2
4
6
8
10
In the following example, we compute the sum of the squares of all values in the list. Note that we need to initialize the sum to zero before we begin the loop.
Example
Compute a sum using thefor
loop.
1sum_squares = 0
2for item in list1:
3 sum_squares = sum_squares + item**2
4print(f"The sum of the squares is {sum_squares}")
The sum of the squares is 220
Mathematically, we are computing the sum:
$$ \sum_{x \in \mathcal{B}} x^2 = 2^2 + 4^2+6^2+8^2+10^2$$
where $\mathcal{B}$ is the set of all elements in list1
.
Recall that only the indented statement is within the for loop. Therefore, the last print statement is not subjected to any iteration. The following shows the inner workings of the for loop for each iteration. The temp
variable is created to store the sum before it is being updated (for the purpose of printing).
Example
Dissecting thefor
loop to compute a sum.
1sum_squares = 0
2for item in list1:
3 temp = sum_squares
4 sum_squares = sum_squares + item**2
5 print(f"{item}: the sum is now {temp} + {item**2} = {sum_squares}")
6print(f"The sum of the squares is {sum_squares}")
2: the sum is now 0 + 4 = 4
4: the sum is now 4 + 16 = 20
6: the sum is now 20 + 36 = 56
8: the sum is now 56 + 64 = 120
10: the sum is now 120 + 100 = 220
The sum of the squares is 220
It is possible to loop over the elements in a Python set (which we may recall is both unordered and unindexed). However, the result may not follow the order in which the items appear in the set.
Example
Looping through a set.1set1 = {2,4,6,8}
2for item in set1:
3 print(item)
8
2
4
6
We can also loop over dictionaries. By default, Python will loop over the keys only.
Example
Looping through a dictionary.1scores = {"Lily":62, "Jane":86, "Tom":75, "Matt":91}
2for item in scores:
3 print(item)
Lily
Jane
Tom
Matt
To loop over the values, we use the values()
method.
Example
Looping through the values of a dictionary.1for item in scores.values():
2 print(item)
62
86
75
91
To loop over the key:value
pairs as tuples, we use the items()
method.
Example
Looping through thekey:value
pairs of a dictionary.
1for item in scores.items():
2 print(item)
('Lily', 62)
('Jane', 86)
('Tom', 75)
('Matt', 91)
We may also separate the keys and the values by creating two loop variables in a tuple.
Example
Looping through a dictionary: separating keys and values.1for (name,score) in scores.items():
2 print(f'{name} receives a score of {score}')
Lily receives a score of 62
Jane receives a score of 86
Tom receives a score of 75
Matt receives a score of 91
ADVERTISEMENT
Some Useful Functions
In this section, we introduce several useful functions related to looping.
The range() Function
We can generate a sequence of integers using the range()
function. For example, range(5)
will generate numbers from 0 to 4 (5 numbers). The syntax is as follows:
Syntax
Therange()
function.
1 range(start, stop, step)
Parameter | Required? | Default Value | Description |
---|---|---|---|
start |
❌ No | 0 | An integer number specifying the start index of the range object. |
stop |
✔️ Yes | NA | An integer number specifying the stop index of the range object. |
step |
❌ No | 1 | An integer number specifying the step size. |
The stop
argument is mandatory. Both the start
and step
arguments are optional. The start argument defaults to 0
and step
argument defaults to 1
if not provided. Note that the range
object produces integers up to but not including the endpoint. The range object evaluates “lazily” in the sense that you will not see the sequence generated unless you explicity convert it to a sequence using the list()
or tuple()
constructors for example.
Example
Therange()
function.
1range(5) # sequence is hidden
range(0, 5)
Example
Converting arange()
object to a list.
1list(range(5)) # convert to list object.
[0, 1, 2, 3, 4]
Example
Converting arange()
object to a tuple.
1tuple(range(5)) # converts to tuple object.
(0, 1, 2, 3, 4)
Example
Therange()
function with start
and stop
arguments.
1list(range(2,8)) # range object with start and stop arguments.
[2, 3, 4, 5, 6, 7]
Example
Therange()
function with all 3 arguments.
1list(range(3,20,2)) # range object with start, stop and step_size arguments.
[3, 5, 7, 9, 11, 13, 15, 17, 19]
We may use the reversed()
function on a range()
object to create the sequence in reversed order.
Example
Thereversed()
function applied to a range()
object.
1list(reversed(range(1,10, 2)))
[9, 7, 5, 3, 1]
Let’s see how the range
object is being used in a for
loop. Let’s compute the sum of the even numbers from $2$ to $100$, i.e. $2+4+6+…+100$.
In mathematical notation, let $\mathcal{S} = \{ x | x \in \mathbb{Z}, 1\leq x \leq 50 \}$ where $\mathbb{Z}$ is the set of all integers. We then compute the sum:
$$ \sum_{i \in \mathcal{S}} 2i = 2 + 4+ 6 + \cdots + 96+98 + 100. $$
Example
Looping through arange()
object.
1total = 0
2for i in range(101):
3 if i % 2 == 0: # modulo operator to ensure that only even numbers get summed
4 total += i
5print(f'Sum of all even numbers from 1 to 100 is {total}')
Sum of all even numbers from 1 to 100 is 2550
In the above code, total += i
is a shorter way of writing total = total + i
. Also, the %
symbol is the modulo character that has been discussed here
. For example, i % 2
computes the remainder when i
is divided by 2
. Consequently, a remainder of 0
means the number i
is divisible by 2
and is even.
There are more efficient methods to compute the sum. One way is to create a range object that contains only the numbers in the series and then apply the sum()
function.
Example
Usingsum()
to compute the sum of a sequence of even numbers.
1numbers = list(range(2,101,2))
2print(f'Sum of all even numbers from 1 to 100 is {sum(numbers)}')
Sum of all even numbers from 1 to 100 is 2550
The enumerate() Function
If you need a counter variable while looping over a sequence, you may use the enumerate()
function. It returns a sequence of (index, element)
tuples. By default, the index starts at zero with a step size of one. Alternatively, you can specify an optional start index. The syntax is as follows:
Syntax
Theenumerate()
function.
1 enumerate(sequence, start)
Parameter | Required? | Default Value | Description |
---|---|---|---|
sequence |
✔️ Yes | NA | An iterable object that supports iteration. |
start |
❌ No | 0 | The index value from which the counter is to be started. |
The sequence
argument is mandatory while the start
argument is optional. The start argument defaults to 0
if not specified.
Example
Usingenumerate()
function in a for
loop.
1fruits= ["apple","orange","banana","pear","pineapple","durian"]
2for item in enumerate(fruits):
3 print(item)
(0, 'apple')
(1, 'orange')
(2, 'banana')
(3, 'pear')
(4, 'pineapple')
(5, 'durian')
If you want to “decouple” the (index, element)
tuple, you can create two loop variables in a tuple.
Example
Decoupling the(index, element)
tuple in enumerate()
.
1for (index, fruit) in enumerate(fruits):
2 print(f'{index}: {fruit}')
0: apple
1: orange
2: banana
3: pear
4: pineapple
5: durian
We can specify an optional start
index in the enumerate function.
Example
Specifying thestart
index in enumerate()
.
1for (index, fruit) in enumerate(fruits,2):
2 print(f'{index}: {fruit}')
2: apple
3: orange
4: banana
5: pear
6: pineapple
7: durian
The random.sample() Function
Since we have discussed the range()
function, we will introduce a closely related function called the random.sample()
function which is part of Python’s random module used to work with random data generation. First, we need to import the module using a import random statement.
Syntax
Importing therandom
module.
1import random
We use random.sample(range(), n)
to generate a list of n
random integers within the specified range()
. Take note that no repetition is allowed. Therefore, the number n
must not be more than the number of integers within the specified range. Essentially, the sample()
function takes the items from the specified range object and mixes them randomly.
Example
Therandom.sample(range(), n)
function.
1random.sample(range(1,11),10) # 10 random integers with range(1,11).
[8, 10, 9, 2, 3, 1, 7, 6, 5, 4]
In the above code, we are generating 10 random integers within the range(1,11)
.
If we had used any value of $n>10$, we will get an error since there are only 10 integers within the specified range and the random integers generated cannot be repeated.
We can get the list sorted using the sorted()
function.
Example
Thesorted()
function to sort a list.
1sorted(random.sample(range(1,11),10))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Example
Thesorted()
function to sort a list (in reverse order).
1sorted(random.sample(range(1,11),10), reverse=True)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
What if you want repetitions of the numbers from the range object? That brings us to the random.choices()
function.
ADVERTISEMENT
The random.choices() Function
We use the random.choices(range(), k=n)
function to select k=n
multiple random items from a range()
object (or any iterable sequence) with repetitions allowed.
Example
Therandom.choices(range(), k=n)
function.
1random.choices(range(1,11),k=10)
[5, 8, 10, 1, 1, 1, 8, 2, 7, 10]
Since repetitions are allowed, the is no limit on the value of k
.
1random.choices(range(1,11),k=15)
[1, 4, 8, 5, 4, 7, 1, 5, 2, 6, 9, 7, 2, 8, 9]
Let’s see how we can use the above random functions with for
loops.
Example
Use a random number generator to simulate the tossing of an unbiased die 10 times and print out the results.1tosses = random.choices(range(1,7),k=10) # generate a list of random integers between 1 and 6, 10 times.
2for (toss,item) in enumerate(tosses,1):
3 print(f'Toss {toss} shows {item}')
Toss 1 shows 1
Toss 2 shows 1
Toss 3 shows 4
Toss 4 shows 4
Toss 5 shows 5
Toss 6 shows 2
Toss 7 shows 4
Toss 8 shows 2
Toss 9 shows 1
Toss 10 shows 6
Answer
1tosses = random.choices(range(1,7),k=100) # generate a list of random integers between 1 and 6, 100 times.
2dict1 = {} # empty dictionary {face: frequency}
3for x in range(1,7):
4 dict1[x] = tosses.count(x)
5 print(f'Face {x} shows {dict1[x]} times')
Face 1 shows 20 times
Face 2 shows 22 times
Face 3 shows 15 times
Face 4 shows 14 times
Face 5 shows 17 times
Face 6 shows 12 times
If you do not wish to store the results in a dictionary but merely want to print out the results, you can use the following shorter code.
1tosses = random.choices(range(1,7),k=100)
2for x in range(1,7):
3 print(f'Face {x} shows {tosses.count(x)} times')
Face 1 shows 20 times
Face 2 shows 22 times
Face 3 shows 15 times
Face 4 shows 14 times
Face 5 shows 17 times
Face 6 shows 12 times
The zip() Function
To loop over two or more sequences (iterables) at the same time, the entries can be paired with the zip()
function to create a list of tuples.
Example
Using thezip()
function to combine 2 iterables into a list of tuples.
1names = ["Lily", "Jane", "Tom", "Matt"]
2scores = [62, 86, 75, 91]
3for (name, score) in zip(names, scores):
4 print(f'{name} receives a score of {score}')
Lily receives a score of 62
Jane receives a score of 86
Tom receives a score of 75
Matt receives a score of 91
We can further add the enumerate()
function to create an index.
Example
Using bothzip()
and enumerate()
functions in a for
loop.
1for (i, (name, score)) in enumerate(zip(names, scores)):
2 print(f'{i}: {name} receives a score of {score}')
0: Lily receives a score of 62
1: Jane receives a score of 86
2: Tom receives a score of 75
3: Matt receives a score of 91
zip()
can take an arbitrary number of sequences, but the number of elements it produces is determined by the shortest sequence.
Example
zip()
function with 3 iterables.
1grades = ['C', 'A', 'B'] # assume grade for the last student isn't available.
2for (name, score, grade) in zip(names, scores, grades):
3 print(f'{name} receives a score of {score} and grade {grade}.')
Lily receives a score of 62 and grade C.
Jane receives a score of 86 and grade A.
Tom receives a score of 75 and grade B.