6. Functions¶
6.1. Introduction¶
Functions can be used to define reusable code and organize and simplify code.
Suppose that for some programming problem you need to find the sum of integers from 11 to 20, 25 to 32, and 39 to 43. If you create a program to add these three sets of numbers, your code might look like this:
sum = 0
for i in range(11, 20):
sum = sum + i
print("Sum from 11 to 20 is", sum)
sum = 0
for i in range(25, 32):
sum = sum + i
print("Sum from 25 to 32 is", sum)
sum = 0
for i in range(39, 43):
sum = sum + i
print("Sum from 39 to 43 is", sum)
You may have observed that the code for computing these sums is very similar, except that the starting and ending integers are different. Wouldn’t it be nice to be able to write commonly used code once and then reuse it? You can do this by defining a so-called function, which enables you to create reusable code. For example, the preceding code can be simplified by using a function that you def (define) yourself as follows:
def sum(i1, i2):
result = 0
for i in range(i1, i2):
result = result + i
return result
print("Sum from 11 to 20 is", sum(11, 20))
print("Sum from 25 to 32 is", sum(25, 32))
print("Sum from 39 to 43 is", sum(39, 43))
This code produces the same output as the earlier code, but is shorter, more ordered, easier to maintain and easier to read.
In earlier chapters, we have already used many functions e.g. float(“3.1415”)` and input(“enter a name: “). In this chapter, you will learn how to define and call our own functions. This will help to solve more complex problems.
6.2. Defining and Calling¶
Fig. 6.1. Elements of definition and invoke (calling) of a function. This example calculates the minimum of two numbers.¶
function definition
A function definition consists of the function’s name, parameters, and body. Figure 6.1 shows the names of all concepts involved in function definition and call. The header begins with the def keyword, followed by the function’s name and parameters, and ends with a colon (:).
The variables in the function header are known as (formal) parameters. A parameter is like a placeholder: When a function is called, you pass values (like a number or a text) to the parameter. These values are referred to as arguments. There are also functions with no parameters. For example, the (built-in) turtle function to clear the canvas turtle.clear() has no parameters.
The function body contains a collection of statements that define what the function does. For example, the function body of the min function uses an if statement to determine which number is smaller and returns the value of that smaller number.
When a program calls a function, the lines of the function body will be executed until its return statement is executed (or the function block is finished).
function call
In a function’s definition, you define what it is to do. To use a function, you have to call or invoke it. The words call and invoke are synonyms here. There are two ways to call a function, depending on whether or not it returns a value. If the function returns a value, a call to that function is usually treated as a value. For example, smaller = min(7, 8) calls min(7, 8) and assigns the return value of the function to variable smaller. Another example of a call that is treated as a value is print(min(7, 8)) which prints the return value of the function call min(7, 8). The keyword return is required for a value-returning function. The line of code that contains return is commonly referred to as the return statement.
If a function does not return a value, the call to the function must be a complete statement. For example, the print function does not return a value. The following call is a statement:
print("Programming is fun!")
More on the possibilities of return values in section ‘Multiple return-values and no return value’.
6.3. Testing and Main()¶
With function definition and calling it is easy to make small mistakes that are hard to debug. Therefore, it is good practice to write small test programs that test a function before it is used in an actual larger program. Here is a little program that could be used to test the min function:
1# program test_min.py
2
3def min(num1, num2):
4 if num1 < num2:
5 result = num1
6 else:
7 result = num2
8 return result
9
10def test_min_for(n1, n2):
11 smaller = min(n1, n2) # call min with the values of n1 and n2
12 print("The smaller number of", n1, "and", n2, "is", smaller)
13 return # could be omitted here, since no value is returned
14
15# testing the min function with different values
16test_min_for(7, 8)
17test_min_for(3.1415, 3.1414)
18test_min_for(-1, -2)
As you can see it consists of the definition of min and the testing part consists of a series of calls to the function with different values. After we have convinced ourselves that function min will give a proper result with any combination of two numbers we can copy the definition in the actual program where it is to be used.
Main()
The testing program above may give some confusion about which statement is executed first, because the first lines of code are only definitions. In this example execution starts at line 16: test_min_for(7, 8). Especially in larger programs you may have many more definitions and the actual first statement to be executed may be hard to find. In such cases it is good practice to define a so-called main() function to make clear where the program starts with the execution.
As an example let’s use main() to clarify exeution in program test_min:
# program test_min_with_main_function.py
def min(num1, num2):
if num1 < num2:
result = num1
else:
result = num2
return result
def test_min_for(n1, n2):
smaller = min(n1, n2) # call min with the values of n1 and n2
print("The smaller number of", n1, "and", n2, "is", smaller)
# return may be omitted here, since no value is returned
def main():
test_min_for(7, 8)
test_min_for(3.1415, 3.1414)
test_min_for(-1, -2)
main() # starts executing the statements in main()
As you can see, the program only consists of definitions and one call to function main() so there is no confusion over which statement is executed first. This practice is so common that in many major programming languages (like Java, C#, C and C++) function main() is compulsory. This way of programming is also advised in this course for all non-trivial Python programs.
6.4. The Scope of Variables¶
Local variables
A variable created inside a function is referred to as a local variable. We have already seen an example: variable result in function min above. Local variables can only be accessed within a function. This concept is called the scope of the variable. The scope of a local variable starts from its creation and continues to the end of the function that contains the variable.
As an illustration, let’s look at this example:
def faculty(num):
result = 1
for n in range(1, num + 1):
result = result * n
return result
number = 4
print(str(number) + "! is", faculty(number))
print(result)
This code results in an error in the output.
4! is 24
Traceback (most recent call last):
File "faculty.py", line 10, in <module>
print(result)
NameError: name 'result' is not defined
The error occurs because variable result ceases to exist (goes ‘out-of-scope’) at the end of the function where it was created (faculty). Scope might seem limiting at first sight, but is actually helpful to prevent confusion in naming. A variable name result is likely to occur in many functions, and because of scoping there is no mixing-up of names. You can always get the values of the local variables by the return.
Let’s fix the example above, with this alternative:
def faculty(num):
result = 1
for n in range(1, num + 1):
result = result * n
return result
num = 4
fac = faculty(number)
print(str(num) + "! =", fac)
print(fac)
Now the value of result has been assigned to variable fac which is still in scope.
Global variables
In Python, you can also use global variables. They exist from the moment they are created until the program terminates. They are created outside all functions and are accessible from everywhere in the code.
Global variables are in accessible inside a function body. Look at this simple example where global variable x is accessed inside function square_x():
def square_x():
result = x * x
return result
x = 4
print(square_x())
The output of this program will be 16 as expected. However, this style of programming is not very flexible because only variable _x_ can be squared by this function. In contrast, the standard form with the value of x passed as an argument allows for any variable as input.
Here is an better alternative with a parameter:
def square(x):
result = x * x
return result
y = 4
print(square(y))
As a rule of thumb, it is always better to pass variable values by argument, than to use global variables. In this course we expect your programs to obey this rule.
6.5. Return values¶
void functions
In Python, it is possible to compose a function without a return statement. Functions like this are called void. As an example of a void function, here is a function that prints an ‘A’ to ‘F’ grade depending on the number of points scored:
# void function print_grade only prints score
def print_grade(score):
if score >= 90.0:
print('A')
elif score >= 80.0:
print('B')
elif score >= 70.0:
print('C')
elif score >= 60.0:
print('D')
else:
print('F')
def main():
score = float(input("Enter a score: "))
while score >= 0:
print_grade(score)
score = float(input("Enter a score: "))
main() # Call the main function
The print_grade() function does not need to return any value, since it’s only purpose is to print something. As a consequence, a return statement is not needed at the end. It is invoked as a statement in function main(): print_grade(score).
As a side remark, every void function does in fact return an automatic, meaningless value of None, Python’s keyword for “nothing”. If you ever see None as an output of a program, chances are that you are dealing with the return value of a void function.
Let’s illustrate the differences between the use of a function that does not return a value and a function that does, let’s modify the print_grade() function to return a value. We call the new function that returns the grade get_grade():
# function get_grade returns grade
def get_grade(score):
if score >= 90.0:
grade = 'A'
elif score >= 80.0:
grade = 'B'
elif score >= 70.0:
grade = 'C'
elif score >= 60.0:
grade = 'D'
else:
grade = 'F'
return grade
def main():
score = float(input("Enter a score: "))
while score >= 0:
grade = get_grade(score)
print("The grade is: ", grade)
score = float(input("Enter a score: "))
main() # Call the main function to start testing
The get_grade() function defined above returns a letter grade based on the numeric score value. It is invoked in the 3rd line of the function body of main(). The get_grade() function returns a character, and it can be invoked and used just like a character. In contrast, the print_grade() function does not return a value, and it must be invoked as a statement.
multiple return values
Python also allows a function to return multiple values. Here is a program with a function that takes two numbers and returns them in descending order, with some testing code:
# multiple_return_value.py
def order(number1, number2):
if number1 < number2:
return number1, number2
else:
return number2, number1
def main():
n1, n2 = order(3, 2)
print("n1 is", n1)
print("n2 is", n2)
main()
The order() function returns two values and you need to pass the returned values in a simultaneous assignment (commas between the variables left of the ‘=’).
© Copyright 2022, dr. P. Lambooij
last updated: Sep 02, 2022