Python: Functions¶
Functions¶
Python has a lot of built-in functions (overview) and we have already used some of them. But what is a function?
A function is a block of code with a name (address), thus it is callable and only executed if it is called.
This also means that you can call a (initialized) function everywhere in the scope (see below) of your program, similar to a variable.
Let’s have a look at the Pure Data example again. Two numbers are added with an operator called +
. Now we will write a function which does the same:
It takes two arguments as inputs and returns the sum of them.
Small program in the visual programming language Pure Data.
Defining a function¶
Functions are stored as variables (or – in terms of Python – as objects) as well, so the naming rules and conventions for variables apply for functions as well of course.
The keyword to define a function is def
, followed by a name of our choice, which we will then use to call the function.
def add_numbers(num1, num2):
# The variables num1 and num2 are accessible
# inside the function.
print(f'{num1} + {num2} is {num1 + num2}')
Inside a function we can write multiple statements (each in one line), which all belong to the function and are executed when we call the function. To mark code as inside a function, all lines are indent by one tab (commonly 4 spaces). The `:` at the end of the `def`-line indicates that we have to indent the following line(s).
If we execute the block of code, we’ll create a new object with the name add_numbers
.
Then we can call our function and insert two values into it. The function will print the result.
add_numbers(3, 5)
'3 + 5 is 8'
left, right = 11, -12
add_numbers(left, right)
'11 + -12 is -1'
Likely you'll need the function
abs()
for that. Try abs(-12)
or help(abs)
to see what it does.
def add_numbers (a, b):
# if b is 0 or positive:
if b >= 0:
print(f'{a} + {b} = {a+b}')
# if b is negative:
else:
print(f'{a} - {abs(b)} = {a+b}')
# another solution:
# print(f'{a} - {b * -1} = {a+b}')
left, right = 11, -12
add_numbers(left, right)
11 - 12 = -1
This can save a lot of time, because we can reuse existing code.
Arguments¶
It’s possible and often useful (for testing, structuring, reusability) to write a function although we want to use it only once. But the strength appears when we need to execute a block of code on multiple occurences in our program. Let’s imagine we have a row of hearts which we want to print on several pages on several positions. We could write the whole code for each occurence or wrap everything in a function and then call this function when needed.
from fpdf import FPDF
Without arguments¶
def print_hearts_top():
heart_01 = '<3' * 50
pdf.set_font('times', '', 15)
pdf.set_xy(10, 10)
pdf.multi_cell(0, 0, txt=heart_01, align='C')
def print_hearts_bottom():
heart_01 = '<3' * 50
pdf.set_font('times', '', 15)
pdf.set_xy(10, 275)
pdf.multi_cell(0, 0, txt=heart_01, align='C')
pdf = FPDF('P', 'mm', format='A4')
pdf.add_page()
print_hearts_top()
print_hearts_bottom()
pdf.output('hearts_001.pdf')
First this looks like more work but if we need the row of hearts again, we just need to call our function and they will be inserted.
With arguments¶
One aim when defining functions is to make them flexible. Flexibility is reached through the use of variables. First we can set the position (set_xy
) as variables, then we can reduce the two functions to one:
def print_hearts(x, y):
heart_01 = '<3' * 50
pdf.set_font('times', '', 15)
# Next we'll use the arguments x and y which we passed to the function
pdf.set_xy(x, y)
pdf.multi_cell(0, 0, txt=heart_01, align='C')
pdf = FPDF('P', 'mm', format='A4')
pdf.add_page()
print_hearts(10, 10)
print_hearts(10, 275)
pdf.output('hearts_002.pdf')
With default arguments¶
When defining a function we can insert default arguments for the variables (parameters). If no arguments are provided when calling the function, the default arguments will be used:
def print_hearts(y, x=10, num=50):
pdf.set_font('times', '', 15)
pdf.set_xy(x, y)
pdf.multi_cell(0, 0, txt='<3' * num, align='C')
We have to take care of the order of the variables. Variables without a default argument have to be placed before variables with default argument.
pdf = FPDF('P', 'mm', format='A4')
pdf.add_page()
print_hearts(y=10)
print_hearts(y=275)
pdf.output('hearts_003.pdf')
Return¶
At the beginning was stated that functions return data. This means that they can give back data after it was processed. This is very useful, because so the data can be stored in a variable again.
def simple_return(data):
return data
d = simple_return('some data')
print(d)
some data
def double_return(data):
return data*2
d = double_return('is a rose ')
print(d)
d = 'A rose' + double_return('is a rose ')
print(d)
is a rose is a rose
A roseis a rose is a rose
def add_numbers(num1, num2):
res = num1 + num2
return res
r = add_numbers(14, 5)
r
19
Scope of variables and functions¶
Variables initiated in the main program (not indented) are accessible globally = everywhere, even inside functions.
x = 1 # global scope
def print_x():
print(x)
print_x()
1
If we define a variable inside of a function, it is available only inside this function:
x = 1
def print_x():
x = 56 # This x is a new variable, avaible only inside the function = local.
print(x)
print_x()
print(x) # The outside x is not affected by the operations inside the function.
56
1
We can change the value of a global variable from inside a function, if we address the global variable through the keyword global
:
def override_x(new_value):
global x
x = new_value
override_x(71)
print(x)
71
The same applies to functions. We can write functions inside functions, which are available only to their parent function. But that belongs to a later session about classes.
def outside_function(x, y):
def inside_function(x, y):
return x + y
return inside_function(x, y)
outside_function(7,4)
11
inside_function(7,4)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-28-158045f32788> in <module>
----> 1 inside_function(7,4)
NameError: name 'inside_function' is not defined
Recursion¶
Q: How do I explain recursion to a 4 year-old?
A: Explain it to someone a year younger than you & ask them to do the same.
Recursion is a topic on its own and this is only a brief introduction. Functions can be recursive which means that they can call themselve from inside themselve.
numbers = [x for x in range(4, 11, 3)]
print(numbers)
def add_recursive(numbers):
if len(numbers) == 1:
return numbers[0]
else:
return numbers[0] + add_recursive(numbers[1:])
summed = add_recursive(numbers)
print(summed)
[4, 7, 10]
21
numbers = [x for x in range(4, 11, 3)]
print(numbers)
def add_recursive(numbers):
if len(numbers) == 1:
return numbers.pop()
else:
numbers[0] += numbers.pop()
return add_recursive(numbers)
summed = add_recursive(numbers)
print(summed)
[4, 7, 10]
21