3.2 Loops#
Let’s do another step to automatize things. 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 — without having to copy your code over and over again!
For loop#
The most common looping technique is a for loop. Let’s see some examples:
# let's create a list with some stuff in it
my_list = [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
# in order to iterate (or go through each element of a list)
# we use a for loop
print('Start of the loop')
for list_item in my_list:
print(f'In my list I can find: {list_item}')
print('End of the loop')
General for loop construction looks like this:
for variable in iterable:
do something with variable
iterable here means something with elements that can be iterated over, think of a list. During each iteration the following steps are happening under the hood:
variable = iterable[0]variableis assigned the first value from the iterable.Then, you use
variableas you wishBy 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 list within the loop?
Let’s see whether we can change the original list within a list with a for loop:
x = [100, 'marble', False, 2, 2, [7, 7, 7], 'end']
print(f'Try #1, before: {x}')
for item in x:
item = [5,6,7]
print(f'Try #1, after: {x}')
Nothing has changed…. let’s try another method.
Here we use range() to generate a sequence of numbers, more info at https://www.w3schools.com/python/ref_func_range.asp
Example range(5) will generate numbers from 0 till 5 (not including 5)
length_of_x = len(x)
print(f'Length of x: {length_of_x}')
indices = range(length_of_x)
print(list(indices)) # print the numbers in the range (converted to a list)
print(f'Try #2, before: {x}')
for id in indices:
x[id] = -1
print(f'Try #2, after: {x}')
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 will first create an empty list to store the greetings, and then use the .append option to add items to the greetings list.
# General greeting
msg = "Ohayo!"
# the list with your friends names
names = ["Jarno", "Alex", "John", "Maria", "Xenia", "Janis", "Vasya"]
# An empty list to store the greetings
greetings = []
for name in names:
personalized_greeting = f'{msg}, {name}-kun!' # create the personalize greeting
greetings.append(personalized_greeting) # append the personalized meeting tot the list of greetings
# Printing our newly created greetings
print(greetings)
And you can also have loops inside loops!
# Let's say that you put down all your expenses per day separately,
# in euros
day1_expenses = [15, 100, 9]
day2_expenses = [200]
day3_expenses = [10, 12, 15, 5, 1]
# you can also keep them within one list together
expenses = [day1_expenses, day2_expenses, day3_expenses]
print(f'All my expenses: {expenses}')
# you can access also each expense separately!
# day3 is third array and 2nd expense is second element
# within that array
print(f'My second expense on day 3 is {expenses[2][1]}')# recall 0th based indexing!
Now assume you would like to calculate the function values \(f(x)=x^3 - 5x -2\) for \(x=[0, 1, 2, 3, 4, 5]\). Below two examples of how we can do that, with and without a for loop.
x = [0, 1, 2, 3, 4, 5]
f = [x[0] ** 3 + 5*x[0] - 2, x[1] ** 3 + 5*x[1] - 2, x[2] ** 3 + 5*x[2] - 2, x[3] ** 3 + 5*x[3] - 2, x[4] ** 3 + 5*x[4] - 2, x[5] ** 3 + 5*x[5] - 2]
print(f'f = {f }')
f = [-2, 4, 16, 40, 82, 148]
You can see above, that a list was created by using the equation for every item in \(x\). A more convenient way is to use a for loop, as shown below. This is especially important if you need to cycle over a large number of items/values.
You can see that we first create an empty list \(f\); in each cycle of the loop, we will then add a new item to \(f\). In order to do so, we use .append (see Section 3.1).
x = [0, 1, 2, 3, 4, 5]
f = []
for i in x:
f.append(x[i] ** 3 + 5*x[i] - 2)
print(f'In this cycle we added f({x[i]}) = {f[i]}')
print(f'f = {f }')
In this cycle we added f(0) = -2
In this cycle we added f(1) = 4
In this cycle we added f(2) = 16
In this cycle we added f(3) = 40
In this cycle we added f(4) = 82
In this cycle we added f(5) = 148
f(x) = [-2, 4, 16, 40, 82, 148]
Now let’s use it in some more calculations.
Option 1: loop over lists using indices \(i\) and \(j\)
Note: this option uses a lot of extra variables to make you understand how loops in loops work. ou will see how this can be compressed in Options 2 and 3.
total_expenses = 0
for i in range(len(expenses)): # loop over all days
# Accessing expenses made at day i + 1
daily_expenses_list = expenses[i]
# Creating temporary storage for current day expenses
daily_expenses = 0
for j in range(len(daily_expenses_list)): # loop over expenses for day i + 1
daily_expenses += daily_expenses_list[j]
# Adding daily expenses to the total expenses
total_expenses += daily_expenses
print(f'Option #1: In total I have spent {total_expenses} euro!')
Option 2: Shorter, directly adding expenses to the grand total
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 3: loop over list items
total_expenses = 0
for day_expenses in expenses:
for e in day_expenses:
total_expenses += e
print(f'Option #3: In total I have spent {total_expenses} euro!')
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 as long as 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(f'sum in the beginning of the cycle: {sum}')
sum += 1
print(f'sum in the end of the cycle: {sum}')
print() # a blank line
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 (use the Kernel menu).
# a, b = 0, 7
# while a + b < 10:
# a += 1
# b -= 1
# print(f'a:{a};b:{b}')
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')
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')
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 of the loop).
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')
As you can see, with the help of the continue keyword we skipped the execution of calculate_cool_function(i)< for all even \(i\). Also worth noting that \(0\) is divisible by any number, for that reason the calculate_cool_function(i) at i = 0 didn’t run.
More about the range function#
range() can be used in three ways:
range(end)range(start, end)range(start, end, step)
It creates a sequence of numbers, from start to end, optionally in steps of step.
Note that the end number itself is not included.
Try it below, and try out some different parameters.
What happens if the start > end?
Can you make range return numbers in descending order by using a negative step?
Does range work with floating point numbers?
We use list() below to convert the range to a list of numbers. Try without list() to see what happens otherwise.
list(range (3, 7))
list(range(3, 17, 2))
#Once you have a range, you can use it in a for loop
for i in range(3, 17, 2):
print(f'i is {i}')
After this Chapter you should be able to:#
understand the differences between
list,tuple, anddictslice lists and tuples
use
forloopsuse
whileloopsuse
breakandcontinuein loopsunderstand
range()