Up to this point, we have already learned how to utilise Python and Jupyter Notebooks to solve a variety of programming scenarios with the help of the essential data types and structures. We also get to know the usage of external packages and the usage of user-defined functions and their vast benefits. Nevertheless, the shown programming approaches have been pretty straightforward so far in a manner of speaking that we only implemented so-called sequentially control flows. This programmatic concept describes a relatively static way of implementation since all our implemented lines of codes (statements) are executed exactly in the order they are written without any possibility of omission. Hence our programming approaches lack the opportunity for flexibility, like a repeated or conditioned execution of certain code blocks.
Therefore, within the scope of this chapter, we want to get to know a variety of standard control flow structures that will allow you to modify and steer the programming flow in your favour. The following control flows will be introduced:
if
, elif
and else
while
for
The first way of steering the code execution is to create branches within the execution flow of your code using conditions. The condition itself must contain a logical statement which is evaluated. Depending on the outcome of the logical expression (either True
or False
), one or the other branch is executed. We use the' if' statement to implement this type of control flow. The general syntax is:
if (logical_expression):
# do a thing
statement_1
statement_2
else:
# do something else
statement_3
statement_4
For example, we could implement a UDF that proves based on your age, if you are a teenager or an adult and returns the results of that evaluation:
def age_test(age):
if (age < 18):
return("You are a teenager!")
else:
return("You are an adult!")
Let us test our nearly implemented, conditioned control flowed UDF by a few different values:
age_test(14)
'You are a teenager!'
age_test(30)
'You are an adult!'
Isn't it great?! Based on our logical expression, the age check age < 18
, and a different output is produced at the given age! Great. Since our example only covers a dichotomic categorisation based on age, we want to implement a broader range of outputs based on the given age. Therefore we make use of the elif
statement and adapt our age_test()
function:
def age_test(age):
if (age <= 0):
return("You are not born yet!")
elif(age <= 10):
return("You are a kid!")
elif(age < 18):
return("You are a teenager!")
elif(age < 65):
return("You are an adult!")
else:
return("You are a retiree!")
Let's try our new version of the function with a few ages:
age_test(5)
'You are a kid!'
age_test(-5)
'You are not born yet!'
age_test(70)
'You are a retiree!'
Another way to steer the control and execution flow is by repeatedly executing a specific code block on purpose with changing values. This programmatic concept is related to the term loops. It is one of the most powerful since it allows you to save many unnecessary LoCs due to little differences. The code statements within the loop are repeated as long as a given condition remains True
or False
based on the chosen implementation or as long as not all elements of a given list are selected once. The first case is related to while
loops, while the second holds for for
loops. For loops in Python are helpful when you want to cycle over all of the items
in a collection (such as all of the elements of an array), and while loops are useful when you want to
cycle for an indefinite amount of time until some condition is met.
for
loops¶At first, we want to look at for
loops since the structure is most likely easier to follow as a beginner.
For a first example, let us use a for loop to print each number between 1 and 10 sequentially:
for i in range(10):
print(i)
0 1 2 3 4 5 6 7 8 9
Oh, that was relatively easy, but the result is unexpected! The reason is that we do not use the range
command appropriately. Since the counting in Python starts with 0
, we must adapt the statement accordingly because we want the first ten numbers without the 0
. Hence:
for i in range(1, 11):
print(i)
1 2 3 4 5 6 7 8 9 10
Note: the
range
command generates a list of values according to the parametrisation. If only one parameter is given, the list will start with $0$ and ends with $n - 1$. If two parameters are given, the list starts with $a$ and ends with $n - 1$.
Awesome! As a next, more advanced task we want to calculate the sum of the first ten numbers with the help of a for
loop:
result = 0
for i in range(11):
result = result + i
print(result)
55
Note on indentation: Notice the indentation once we enter the for loop. Every idented statement after the for loop declaration is part of the for loop. This rule holds true for while loops, if statements, functions, etc. Required identation is one of the reasons Python is such a beautiful language to read.
Nice! We can also simplify the loop by the use of the +=
operator:
result = 0
for i in range(11):
result += i
print(result)
55
Exercise: Externalise the above code within a UDF named
sum_of_numbers()
. The UDF shall take one parameter. Adapt the code so that this parameter steers up to which natural number the sum will be calculated.
### your solution
def sum_of_numbers(a):
result = 0
for i in range(a + 1):
result += i
return(result)
Test your function:
The sum of the first $100$ natural numbers should be $5050$, while the sum of the first $500$ natural numbers should be $125250$.
sum_of_numbers(100)
5050
sum_of_numbers(500)
125250
We may as well loop through any iterable object, such as a list of strings. Let us create a list of different names for those purposes:
names = ["John", "Ringo", "Paul", "George"]
Now let's print each name in the list one by one:
for name in names:
print(name)
John Ringo Paul George
Note: By using
in
, each value within the listnames
is assigned sequentially and once to the variable name once! That makes thefor
loop quite handy and clearly implemented.
Exercise: Combine the items from the two given lists
names
andsurnames
and print them as one string to the console each!Hint: You may want to investigate the use of the
enumerate()
and thezip()
functions on your own with the help of the internet to find a handy and short solution for this task!
names = ["John", "Ringo", "Paul", "George"]
surnames = ["Lennon", "Star", "McCartney", "Harrison"]
### your solution
for i, name in enumerate(names):
print(name, surnames[i])
print("-----")
John Lennon ----- Ringo Star ----- Paul McCartney ----- George Harrison -----
for name_comb in zip(names, surnames):
print(name_comb[0], name_comb[1])
print("-----")
John Lennon ----- Ringo Star ----- Paul McCartney ----- George Harrison -----
while
loops¶A while
loop repeats a task until a particular condition is met. Therefore, we do not need to know how often the loop will be executed. Be sure there is a way to exit out of a while loop. Otherwise, your program will run forever.
Let's implement the same task with which we introduced the for
loop, but this time by using a while
loop. That means using a while
loop that prints the first ten natural numbers sequentially:
i = 1
while(i <= 10):
print(i)
i += 1
1 2 3 4 5 6 7 8 9 10
Now, we want to adapt the above loop so that only every second number starting with $2$ is printed:
i = 2
while(i <= 10):
print(i)
i += 2
2 4 6 8 10
There is also the possibility of using an if
statement within the loop to achieve the same result. We want to have a look at that solution by printing all even numbers from $0$ to $25$:
number = 0
while (number <= 25):
if ((number % 2) == 0):
print(number)
number += 1
0 2 4 6 8 10 12 14 16 18 20 22 24
Exercise: Write a parameterised UDF called
fibo_numbers()
, that calculates the fibonacci numbers according to the given parameter! Use awhile
loop for this task.
### your solution
def fibo_numbers(end):
a = 0
fibo_list = []
while (a <= (end - 1)):
if (a < 2):
fibo_list.append(1)
else:
fibo_list.append(fibo_list[a-2] + fibo_list[a-1])
a += 1
return(fibo_list)
Test your function:
The first 10 fibonacci numbers are:
fibo_numbers(10)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Finally, we want to conclude this section by applying our knowledge of UDFs and control statements to build a small program, called guess_a_number
. The program is all about guessing a random integer within a given range of guesses. Copy the following two cells to your Jupyter notebook and start the game with the function call guess_a_number(<max_value>, <trials>)
.
def ask_for_guess(max_value, trial):
print("Guess a natural number between 1 and ", max_value, "!")
text = print("Trial ", trial, " - Your guess:")
guess = input(text)
try:
guess = int(guess)
succ = True
except ValueError:
succ = False
if (succ == False):
print("Please provide a natural number!")
guess = ask_for_guess(max_value, trial)
return guess
import random
def guess_a_number(max_value = 100, number_of_trials = 10):
"""
Function do initialize the game.
You can adapt the number of maximum trials as well as the value range
"""
secret_number = random.choice(range(1, max_value))
trial = 1
success = False
while (trial <= number_of_trials):
guess = ask_for_guess(max_value, trial)
if (guess == secret_number):
print("Congratulation! You have sucessfully guess the right number in ", trial, " trials.")
success = True
break
elif (guess < secret_number):
print("The number is bigger!")
else:
print("The number is smaller!")
print(number_of_trials - trial, " trials left.")
trial += 1
if (success == False):
print("Sorry, game over you exceeded your maximum trial count!")
guess_a_number(10, 3)
Citation
The E-Learning project SOGA-Py was developed at the Department of Earth Sciences by Annette Rudolph, Joachim Krois and Kai Hartmann. You can reach us via mail by soga[at]zedat.fu-berlin.de.
Please cite as follow: Rudolph, A., Krois, J., Hartmann, K. (2023): Statistics and Geodata Analysis using Python (SOGA-Py). Department of Earth Sciences, Freie Universitaet Berlin.