2.3. Loops#
Let’s do another step to automatize things even more! Previous Sections introduced a lot of fundamental concepts, but they still don’t unveil the true power of any programming language — loops!
If we want to perform the same procedure multiple times, then we would have to take the same code and copy-paste it. This approach would work, however it would require a lot of manual work and it does not look cool.
This problem is resolved with a loop construction. As the name suggest, this construction allows you to loop (or run) certain piece of code several times at one execution.
2.3.1. for
loop#
The first and the most popular looping technique is a for
loop. Let’s see some examples:
Let’s create a list with some stuff in it. In order to iterate (or go through each element of a list) we use a for
loop.
my_list = [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
print('Start of the loop')
for list_item in my_list:
print('In my list I can find:', list_item)
print('End of the loop')
Start of the loop
In my list I can find: 100
In my list I can find: marble
In my list I can find: False
In my list I can find: 2
In my list I can find: 2
In my list I can find: [7, 7, 7]
In my list I can find: end
End of the loop
General for
loop construction looks like this:
for iterator_variable in iterable:
do something with iterator_variable
During each iteration the following steps are happening under the hood (or above it):
iterator_variable = iterable[0]
iterator_variable is assigned the first value from the iterable.Then, you use iterator_variable as you wish.
By the end of the ‘cycle’, the next element from the iterable is selected (
iterable[1]
), i.e., we return to step 1, but now assigning the second element… and so on.When there is not a next element (in other words, we have reached the end of the iterable) — it exits and the code under the loop is now executed.
Looks cool, but what if we want to alter the original iterable (not the iterator_variable
) within the loop?
x = my_list
print('Try #1, before:', x)
for item in x:
item = [5,6,7]
print('Try #1, after', x)
Try #1, before: [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
Try #1, after [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
Nothing has changed…. let’s try another method. range()
is used to generate a sequence of numbers more info here.
range(length_of_x)
will generate numbers from 0 till length_of_x
, excluding the last one.
length_of_x = len(x)
indices = range(length_of_x)
print(indices)
print('Try #2, before', my_list)
for id in indices:
my_list[id] = -1
print('Try #2, after', my_list)
range(0, 7)
Try #2, before [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
Try #2, after [-1, -1, -1, -1, -1, -1, -1]
Now we have a method in our arsenal which can not only loop through a list but also access and alter its contents. Also, you can generate new data by using a for
loop and by applying some processing to it. Here’s an example on how you can automatize your greetings routine!
We create a variable message
with a general greeting and a list with your friends names. Then an empty list where all greetings will be stored (otherwise you cannot use the .append
in the for loop below!).
message = "Ohayo"
names = ["Mike", "Alex", "Maria"]
greetings = []
for name in names:
personalized_greeting = f'{message}, {name}-kun!'
greetings.append(personalized_greeting)
print(greetings)
['Ohayo, Mike-kun!', 'Ohayo, Alex-kun!', 'Ohayo, Maria-kun!']
And you can also have loops inside loops!. Let’s say that you put down all your expenses per day separately in euros. You can also keep them within one list together.Additionally, you can access also each expense separately! day3 is third array and 2nd expense is second element within that array.
day1_expenses = [15, 100, 9]
day2_expenses = [200]
day3_expenses = [10, 12, 15, 5, 1]
expenses = [day1_expenses, day2_expenses, day3_expenses]
print('All my expenses', expenses)
print(f'My second expense on day 3 is {expenses[2][1]}')
All my expenses [[15, 100, 9], [200], [10, 12, 15, 5, 1]]
My second expense on day 3 is 12
Now let’s use it in some calculations. The code bellow iterates over the expenses for each day, calculates the total expenses for each day, and then adds them together to obtain the overall total expenses.
total_expenses = 0
for i in range(len(expenses)):
daily_expenses_list = expenses[i]
daily_expenses = 0
for j in range(len(daily_expenses_list)):
daily_expenses += daily_expenses_list[j]
total_expenses += daily_expenses
print(f'Option #1: In total I have spent {total_expenses} euro!')
Option #1: In total I have spent 367 euro!
Let’s break it down
This code calculates the total expenses over multiple days using nested loops. Here’s an explanation in simpler terms:
We start with the variable
total_expenses
set to 0 to keep track of the total expenses.The code loops over each day’s expenses using the outer loop, which runs from 0 to the length of the
expenses
list.Inside the loop, it accesses the expenses made on the current day by assigning
daily_expenses_list
to the expenses at indexi
.It initializes
daily_expenses
as 0 to temporarily store the sum of expenses for the current day.The code enters the inner loop, which iterates over the expenses for the current day using the range of the length of
daily_expenses_list
.Inside the inner loop, it adds each expense to
daily_expenses
to calculate the total expenses for the current day.After the inner loop completes, it adds
daily_expenses
to thetotal_expenses
variable to accumulate the expenses across all days.Once the outer loop finishes, it prints the total expenses using an f-string format to display the result.
Option #2
total_expenses = 0
for i in range(len(expenses)):
for j in range(len(expenses[i])):
total_expenses += expenses[i][j]
print(f'Option #2: In total I have spent {total_expenses} euro!')
Option #2: In total I have spent 367 euro!
Option #3 - advanced techniques gathered after eternal suffering.
total_expenses = 0
total_expenses = sum(map(sum, expenses))
print(f'Option #3: In total I have spent {total_expenses} euro!')
Option #3: In total I have spent 367 euro!
2.3.2. while
loop#
The second popular loop construction is a while
loop. The main difference is that it is suited for code structures that must repeat unless a certain logical condition is satisfied. It looks like this:
while logical_condition == True:
do something
And here is a working code example:
sum = 0
while sum < 5:
print('sum in the beginning of the cycle:', sum)
sum += 1
print('sum in the end of the cycle:', sum)
sum in the beginning of the cycle: 0
sum in the end of the cycle: 1
sum in the beginning of the cycle: 1
sum in the end of the cycle: 2
sum in the beginning of the cycle: 2
sum in the end of the cycle: 3
sum in the beginning of the cycle: 3
sum in the end of the cycle: 4
sum in the beginning of the cycle: 4
sum in the end of the cycle: 5
As you can see, this loop was used to increase the value of the sum variable until it reached \(5\). The moment it reached \(5\) and the loop condition was checked — it returned False
and, therefore, the loop stopped.
Additionally, it is worth to mention that the code inside the loop was altering the variable used in the loop condition statement, which allowed it to first run, and then stop. In the case where the code doesn’t alter the loop condition, it won’t stop (infinite loop), unless another special word is used.
Here’s a simple example of an infinite loop, which you may run (by removing the #’s) but in order to stop it — you have to interrupt the Notebook’s kernel or restart it.
# a, b = 0, 7
# while a + b < 10:
# a += 1
# b -= 1
# print(f'a:{a};b:{b}')
2.3.3. break
keyword#
After meeting and understanding the loop constructions, we can add a bit more control to it. For example, it would be nice to exit a loop earlier than it ends — in order to avoid infinite loops or just in case there is no need to run the loop further. This can be achieved by using the break
keyword. The moment this keyword is executed, the code exits from the current loop.
stop_iteration = 4
print('Before normal loop')
for i in range(7):
print(f'{i} iteration and still running...')
print('After normal loop')
print('Before interrupted loop')
for i in range(7):
print(f'{i} iteration and still running...')
if i == stop_iteration:
print('Leaving the loop')
break
print('After interupted loop')
Before normal loop
0 iteration and still running...
1 iteration and still running...
2 iteration and still running...
3 iteration and still running...
4 iteration and still running...
5 iteration and still running...
6 iteration and still running...
After normal loop
Before interrupted loop
0 iteration and still running...
1 iteration and still running...
2 iteration and still running...
3 iteration and still running...
4 iteration and still running...
Leaving the loop
After interupted loop
The second loop shows how a small intrusion of an if
statement and the break
keyword can help us with stopping the loop earlier. The same word can be also used in a while
loop:
iteration_number = 0
print('Before the loop')
while True:
iteration_number += 1
print(f'Inside the loop #{iteration_number}')
if iteration_number > 5:
print('Too many iterations is bad for your health')
break
print('After the loop')
Before the loop
Inside the loop #1
Inside the loop #2
Inside the loop #3
Inside the loop #4
Inside the loop #5
Inside the loop #6
Too many iterations is bad for your health
After the loop
2.3.4. continue
keyword#
Another possibility to be more flexible when using loops is to use the continue
keyword.
This will allow you to skip some iterations (more precisely — the moment the keyword is used it will skip the code underneath it and will start the next iteration from the beginning).
def calculate_cool_function(arg):
res = 7 * arg ** 2 + 5 * arg + 3
print(f'Calculating cool function for {arg} -> f({arg}) = {res}')
print('Begin normal loop\n')
for i in range(7):
print(f'{i} iteration and still running...')
calculate_cool_function(i)
print('\nEnd normal loop\n')
print('-------------------')
print('Begin altered loop\n')
for i in range(7):
print(f'{i} iteration and still running...')
# skipping every even iteration
if i % 2 == 0:
continue
calculate_cool_function(i)
print('\nEnd altered loop')
Begin normal loop
0 iteration and still running...
Calculating cool function for 0 -> f(0) = 3
1 iteration and still running...
Calculating cool function for 1 -> f(1) = 15
2 iteration and still running...
Calculating cool function for 2 -> f(2) = 41
3 iteration and still running...
Calculating cool function for 3 -> f(3) = 81
4 iteration and still running...
Calculating cool function for 4 -> f(4) = 135
5 iteration and still running...
Calculating cool function for 5 -> f(5) = 203
6 iteration and still running...
Calculating cool function for 6 -> f(6) = 285
End normal loop
-------------------
Begin altered loop
0 iteration and still running...
1 iteration and still running...
Calculating cool function for 1 -> f(1) = 15
2 iteration and still running...
3 iteration and still running...
Calculating cool function for 3 -> f(3) = 81
4 iteration and still running...
5 iteration and still running...
Calculating cool function for 5 -> f(5) = 203
6 iteration and still running...
End altered loop
As you can see, with the help of the continue
keyword we managed to skip some of the iterations. Also worth noting that \(0\) is divisible by any number, for that reason the calculate_cool_function(i)
at i = 0
didn’t run.
2.3.5. Additional study material#
Official Python Documentation - https://docs.python.org/3/tutorial/controlflow.html
Think Python (2nd ed.) - Section 5
Official Python Documentation - https://docs.python.org/3/tutorial/datastructures.html
Think Python (2nd ed.) - Sections 8, 10, 11, 12
Official Python Documentation - https://docs.python.org/3/tutorial/controlflow.html
Think Python (2nd ed.) - Section 7
2.3.5.1. After this Notebook you should be able to:#
generate an array for the x-axis
calculate the
cos
orsin
of the x-axisplot such functions
understand how to load Python files as modules
understand conditions with
if
,elif
and,else
understand the differences between
list
,tuple
, anddict
slice lists and tuples
use
for
andwhile
loopsuse the
break
andcontinue
keywords inside of loops