Nested loops#
You’ve heard of a list inside a list inside a list inside a list etc, a nested list, but what about a loop inside a loop inside a loop inside a loop…
list_1 = [1, 2, 3]
list_2 = ['a', 'b', 'c']
for item_i in list_1:
for item_j in list_2:
print(item_i, item_j)
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
3 c
Sure enough, this is a nested loop: let’s try to figure out what the heck it’s doing.
The first thing to note about this example is the print
statement, which here takes two arguments. Previously, we have only ever supplied one input to the print
function:
a = 5
print(a)
5
But as it happens, the print
function will accept any number of arguments:
a = 5
b = 10
c = 200
print(a, b, c)
5 10 200
It simply prints each argument one after another with a space inbetween each.
Coming back to our nested loop, we can make its inner workings a little clearer with the enumerate
function and an extra print
statement:
list_1 = [1, 2, 3]
list_2 = ['a', 'b', 'c']
for iteration_count, item_i in enumerate(list_1):
print(f'Outer loop iteration #{iteration_count}')
for item_j in list_2:
print(item_i, item_j)
Outer loop iteration #0
1 a
1 b
1 c
Outer loop iteration #1
2 a
2 b
2 c
Outer loop iteration #2
3 a
3 b
3 c
Here we have used the enumerate
function just like we did before, storing the iteration that we are currently on in a variable iteration_count
. Our code now keeps track of iterations associated with the outer loop, i.e. the loop established before the indentation starts, but what if we apply the same trick to the inner loop?
list_1 = [1, 2, 3]
list_2 = ['a', 'b', 'c']
for iteration_count_i, item_i in enumerate(list_1):
print(f'Outer loop iteration #{iteration_count_i}')
for iteration_count_j, item_j in enumerate(list_2):
print(f'Inner loop iteration #{iteration_count_j}')
print(item_i, item_j)
Outer loop iteration #0
Inner loop iteration #0
1 a
Inner loop iteration #1
1 b
Inner loop iteration #2
1 c
Outer loop iteration #1
Inner loop iteration #0
2 a
Inner loop iteration #1
2 b
Inner loop iteration #2
2 c
Outer loop iteration #2
Inner loop iteration #0
3 a
Inner loop iteration #1
3 b
Inner loop iteration #2
3 c
Hopefully you can see that for every iteration of the outer loop, the inner loop iterates through the entirety of list_2
. In other words, the inner loop does all of its iterations before the outer loop iterates again.
Coming back to our original example:
list_1 = [1, 2, 3]
list_2 = ['a', 'b', 'c']
for item_i in list_1:
for item_j in list_2:
print(item_i, item_j)
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
3 c
Let’s go through the first few iterations of this logic manually. On the first iteration of the outer loop, we assign the first element of list_1
to item_i
:
item_i = 1
We then enter the inner loop which, on its first iteration, will assign the first element of list_2
to item_j
:
item_j = 'a'
We then run the rest of the code:
print(item_i, item_j)
Which gives us 1 a
.
At this point, we go into the second iteration of the inner loop, assigning the second element of list_2
to item_j
:
item_j = 'b'
Once again, we run the code within the inner loop:
print(item_i, item_j)
item_i
has not changed, as we are still on the first iteration of the outer loop. On the other hand, item_j
has changed, as we are now on the second iteration of the inner loop, so we get 1 b
.
We will continue iterating through the inner loop until we have been through all of list_2
, at which point the outer loop iterates and item_i
is finally updated:
item_i = 2
We then enter the inner loop again, so item_j
is reset to the first element of list_2
:
item_j = 'a'
So the print
statement gives us 2 a
and so on and so forth.
Let’s go over one more example in a slightly different context:
nested_list = [[1, 2, 3],
['a', 'b', 'c']]
for sublist in nested_list:
for element in sublist:
print(element)
1
2
3
a
b
c
Here we have a list of lists which is just a combination of list_1
and list_2
from our previous example.
The outer loop is iterating through each element of nested_list
. In this case, nested_list
contains two sublists: [1, 2, 3]
and ['a', 'b', 'c']
. The inner loop is iterating through each element of the sublist assigned by the outer loop.
Exercises#
1. Consider the following loop in a loop (nested loop):
rows = 10
for i in range(0, rows):
for j in range(0, i):
print('*', end=' ')
print('')
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
Note
For the time being, ignore the end=' '
argument to the print
function. This ensures that the pattern is displayed correctly by preventing a new line being added after each *. You will not have to change this line of code.
Modify this block of code to produce the following pattern (ignore the colour):
* * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
*