Functions and Loops¶
What you’ll learn
How to split up a problem into smaller parts using functions
How to define and call functions
How to test functions
How to repeat code using
while
andfor
loopsRelational operators
Boolean variables
Functions¶
A function is a group of related statements that performs a specific task. With the help of functions, we can break our program into smaller and modular chunks. So, as we start to write larger programs, functions help us to make it more organized and manageable.
Furthermore, with the help of function, we can avoid repetition and make our code reusable. Let’s start with a very simple example.
The following code sets the variable name1
then prints a simple greeting message:
name1 = "Prof Thomas"
print("Hello", name1)
print("Nice to meet you.")
Hello Prof Thomas
Nice to meet you.
Suppose we would like to print similar greeting messages for each of the variables name1
, name2
and name3
. It is of course possible to do this by simply repeating the code three times:
name1 = "Prof Thomas"
name2 = "Mr Bentham"
name3 = "Prof Lonsdale"
print("Hello", name1)
print("Nice to meet you.")
print("Hello", name2)
print("Nice to meet you.")
print("Hello", name3)
print("Nice to meet you.")
Hello Prof Thomas
Nice to meet you.
Hello Mr Bentham
Nice to meet you.
Hello Prof Lonsdale
Nice to meet you.
However, instead of repeating the identical code three times, we can write a Python function, a named sequence of instructions. In the code below, we define a function called greet
. We then call the function three times, passing in each of our three variables name1
, name2
and name3
.
def greet(name):
print("Hello ", name)
print("Nice to meet you.")
greet("Prof Thomas")
greet("Mr Bentham")
greet("Prof Lonsdale")
Hello Prof Thomas
Nice to meet you.
Hello Mr Bentham
Nice to meet you.
Hello Prof Lonsdale
Nice to meet you.
Let’s examine what the Python interpreter does when it executes the above code.
First, it reads the line
def greet(name):
. When Python reaches this line, it doesn’t actually execute any of the code within this block. Instead, it skips to the next line of code below the function, in this case the linegreet("Prof Thomas")
.At this point, it recognises that
greet
is a previously defined function. Execution now moves to first line of thegreet
function, with the parameter variablename
set to"Prof Thomas"
.Python executes each line of code in the function in order.
Once the interpreter reaches the final line of code in the function, execution returns to the main body of code and the line
greet("Mr Bentham")
is executed. Execution moves to thegreet
function withname = "Mr Bentham"
, and execution continues as described above.
Defining Functions¶
In this section, we will implement a function with a given specification, and call it with some test inputs.
Suppose we want to define a function which computes the perimeter of a rectangle with given length and width. We need to do the following:
Choose a name for the function (
calculate_perimeter
)Define a variable for each argument (
length
andwidth
). These are called parameter variablesPut these together with the keyword
def
and a colon (:
)
def calculate_perimeter(length, width):
Specify the body of the function, which consists of statements which will run when the function is called. The perimeter of a rectangle is twice the length plus the width.
Finally we use the
return
statement to return the result of the function.
def calculate_perimeter(length, width):
perimeter = 2 * (length + width)
return perimeter
Note
The body of the function is indented by 4 spaces
Nothing appears to happen when we run this code on its own - because we haven’t called the function yet
The
perimeter
variable, defined inside the function, is not accessible outside the functionThe
return
keyword is optional
Calling Functions¶
If you run the preceding code nothing happens. In order to test the function, we need to write some statements that call the function and print the result.
def calculate_perimeter(length, width):
perimeter = 2 * (length + width)
return perimeter
x1 = calculate_perimeter(2, 4)
x2 = calculate_perimeter(10, 10)
print("Rectangle 1 perimeter:", x1)
print("Rectangle 2 perimeter:", x2)
Rectangle 1 perimeter: 12
Rectangle 2 perimeter: 40
Because the calculate perimeter
function returns a number, we can use the function call in place of a numeric variable. For example, to print the total perimeter of two rectangles:
print("Total perimeter of rectangles:", calculate_perimeter(2, 4) + calculate_perimeter(10, 10))
Total perimeter of rectangles: 52
Note
The function definition must precede any statements which call it
Warning
The following function contains a common error: trying to modify an argument.
def add_four(x):
x = x + 4 # Has no effect outside the function.
return x
x = 10
add_four(x) # Does not modify x.
x = add_four(x)
print(x)
Example: Splitting a problem into parts¶
Consider following problem:
Given a number n
between 1 and 365, print the day of the week, given 1st January is a Monday.
We can split this into two problems:
Given
n
from 1 to 365, calculate a number between 0 and 6 identifying the day of the weekGiven a number between 0 and 6, determine the day of the week in text form (Monday, Tuesday, etc.)
We can write two functions each of which performs one of these steps, then chain them together.
The first function, get_number_of_day
, returns a number between 0 and 6 given a number n
from 1 to 365:
def get_number_of_day(n):
d = n % 7
return n
The second function, get_day_of_week
, returns a string given a number between 0 and 6:
def get_day_of_week(n):
week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
return week_days[n]
Finally, we write a function get_day_of_week_from_number_of_year
which takes a number between 1 and 365 and prints the day of the week:
def get_day_of_week_from_number_of_year(n):
d = get_number_of_day(n)
s = get_day_of_week(d)
return s
Now we can test it:
day = get_day_of_week_from_number_of_year(1)
print(day)
Tuesday
Wait! It didn’t work: the answer should be Monday
. Let’s investigate. First, let’s check the function get_day_of_week
. Given the value 0, it should return Monday
:
get_day_of_week(0)
'Monday'
So that’s working OK. Let’s test get_number_of_day
. Since the 1st day of the year is a Monday, get_number_of_day(1)
should return 0:
get_number_of_day(1)
1
Aha! We forgot to subtract 1 to change from 1-based indexing to 0-based indexing. In one of the practice exercises, you will fix the error.
Testing Functions¶
By splitting the problem into small functions, we were able to test each part separately, and easily identify where the error was. This is one of the key benefits of using functions.
A common techniques is called test-first development, where the tests are written before writing the function.
def highest_common_factor(a, b):
# replace this line with the function contents
pass
# should print 3
print(highest_common_factor(6, 3))
# should print 5
print(highest_common_factor(5, 5))
Loops¶
A loop is a sequence of instructions which is executed repeatedly until a goal is reached. We’ve already seen the while
loop which repeats a code block while a condition is true.
while
Loops¶
In Python we use a while
statement to repeat a sequence of statements while a specific condition is satisfied.
pop = 10 # initial population
year = 0 # initial year
while pop < 1000: # repeat the following statements while pop is less than 1000
year = year + 1 # update the year
pop = pop * 2 # update the population
print("Number of years:", year)
Number of years: 7
Note
The
while
statement is terminated by a colon (:
)The
while
condition ispop < 1000
The indented lines below the
while
statement are executed repeatedly while the condition is true
Relational Operators¶
The less-than operator <
is a relational operator. It compares two expressions and evaluates to true
if the expression on the left is less than the expression on the right. Other relational operators include the equality operator ==
which evaluates to true
if the expression on the left is equal to the expression on the right. Relational operators can be used in if
statements or while
loops.
Symbol |
Operator |
---|---|
< |
less than |
<= |
less than or equal |
> |
greater than |
>= |
greater than or equal |
== |
equals |
!= |
does not equal |
Warning
It is very easy to make a mistake by choosing the wrong operator. For example, if we replaced pop < 1000
with pop > 1000
in the above code, the while
loop is never entered since the condition is false on the first iteration.
Boolean Variables¶
We can assign the result of a relational operation to a variable. Such a variable has the value True
or False
and is called a Boolean Variable.
x = 5
y = 6
z = x > y
print(x, "is greater than", y, ":", z)
5 is greater than 6 : False
for
Loops¶
A for
loop is used to iterate over a sequence of elements. The simplest form of the for
statement is to iterate over a range of integer values. For example, the following code will execute the indented statements once for each integer from 5 to 9:
for i in range(5, 10):
print("i =", i)
i = 5
i = 6
i = 7
i = 8
i = 9
The range
function specifies the sequence of integer values that the loop variable will take. range(a, b)
generates a sequence starting at a
and ending at b - 1
.
To generate a sequence with a different step size, pass a third argument to the range
function:
for i in range(1, 10, 2):
print("i =", i)
i = 1
i = 3
i = 5
i = 7
i = 9
You can use the range function with a single argument, in which case the range of values starts at zero:
for i in range(5):
print("i =", i)
i = 0
i = 1
i = 2
i = 3
i = 4
Note
The loop variable
i
is updated each loop iterationThe for statement is terminated by a colon (
:
)The indented lines below the
for
statement are executed once for each integer specified by therange
functionThe range function includes the lower limit but excludes the upper limit
Nested Loops¶
For loops may be nested by placing one inside another. The following example repeats in the inner loop 4 times for each of the out loop, resulting in a total of 20 iterations,.
for i in range(5):
for j in range(4):
print(i, j, end="")
print()
0 00 10 20 3
1 01 11 21 3
2 02 12 22 3
3 03 13 23 3
4 04 14 24 3
Note
By default, the print
function adds a newline character, which means that consecutive calls to print
results in output on separate lines.
To avoid this, and use print("text", end="")
.