Python Basics: Functions

Functions are the building blocks of programming.

A function is block of code which is used to execute a task/action or data transformation. It can be called multiple times, with different inputs.

We will decipher this definition in the following blog post. I will explain how to define a function in Python and how it can be called multiple times with different inputs. Using a function can make your code clearer, more organised and more readable. I will give a few use cases to illustrate this.

Usually the first thing you learn in Python (or any programming language) is to display the sentence “Hello World!” to the terminal output. This is how the code would look like:

print("Hello World!")

Here what we are actually doing is calling the built-in print function with a string as argument with the value "Hello World!".

You could simplify and imagine the print function to be defined the following way:

def print(value):
    # do something with the value to 
    # display it on the terminal output.
    # ...
    return None

This imaginary print function has a parameter called value. It then displays the value to the terminal and returns None. We will explain in more details what is a parameter a and what is a return statement later.

The print function is very valuable because you do not need to know how the value you give it is printed to the terminal, you only care about the result. It is used a lot of times throughout programs. The name print clearly states the intent of the function, which is to display or print to the terminal output.

Similarly, when we build our own functions, we will try to:

  • hide implementation details
  • give them a meaningful name
  • make them as reusable as possible

Building your own functions

In Python, you can use many built-in functions, meaning functions that come with the language such as print, len (you can find more details about built-in functions here). More importantly, you can define your own functions in your programs, this is what we will focus on from now on.

How to define a function

To define your own function, you need to:

  • start with the keyword def
  • after that you need parenthesis with, optionally, the parameters of your function
  • then you need a semicollon to start your function block
  • finally the block or content of the function (what it does)

The first line when you define a function is called the function signature, it has the keyword (def) the name of the function and optionally some parameters.

Remember that all the code in your function should be indented inside the function block.

Defining a function with no parameters

Here is an example of what is described above for a function with no parameters:

def my_first_function():
    print("Hello inside a function!")

Here the name of the function is my_first_function, it takes no parameters: there is nothing inside the parenthesis. It then calls the print built-in function.

Defining a function with parameters

Here are two examples of functions with parameters:

def greeting(name):
    print(f"Hello {name}, from inside a function!")

def polite_greeting(title, surname):
    print(f"Dear {title} {surname}, greetings from inside a function!")

Here the name of the first function is greeting, it takes one parameter called name (inside the parenthesis).

The name of the second function is polite_greeting, it takes two parameters called title and surname (inside the parenthesis).

Again, they both call the print built-in function, this time with a f-string.

Once you have defined your functions, if you try to run your program, you will see that nothing happens. This is expected: for your functions to be executed you will need to call them.

How to call a function

Calling a function is equivalent to executing the code inside your function. It will be called with the arguments (or values) that you pass to it.

To call your first function, you simply do the following:

my_first_function()

This has to be below your function definition in your program.

You can call it multiple times, it will execute the code inside your functions each time:

my_first_function()
my_first_function()
my_first_function()

To call the greetings functions, which take parameters there are multiple ways. I will illustrate below 3 different ways:

1. With inline variables

In this method, we directly pass inline values to the function:

greeting("Jane")
polite_greeting("Mrs", "Jackson")
  • We pass the value "Jane" directly to the greeting function. When the function is executed, we have name="Jane" inside the function block.

  • We pass the value "Mrs" and "Jackson" directly to the polite_greeting function. When the function is executed, we have title="Mrs" surnname="Jackson" inside the function block.

2. With existing variable(s)

In this method, we pass existing variables to the function:

first_name = "John"
greeting(first_name)
title = "Dr"
surname = "Jackson"
polite_greeting(title, surname)
  • We pass the variable first_name to the greeting function. When the function is executed, we have name=first_name inside the function block (which is equivalent to name="John").

  • We pass the variables title and surname to the polite_greeting function. When the function is executed, we have title=title surnname=surname inside the function block (which is equivalent to title="Dr" surnname="Jackson").

Here it is important to note that the variable we pass the function (called argument) does not have to have the same name as the function parameter.

3. With keyword arguments

In this method, we can pass either inline values or variable using the parameter name explicitly followed by an equal sign: This method is more verbose, but it is in my opinion is the more intuitive one when learning:

first_name = "John"
greeting(name=first_name)
title = "Dr"
surname = "Jackson"
polite_greeting(title=title, surname=surname)

We are explicitly saying that we want the variable inside our greeting function block name to be first_name when we call it.

Here is an example with inline values:

polite_greeting(title="Mrs", surname="Jackson")

Function return statement in Python

For your functions to be useful in your program, it is common for them to execute some kind of data transformation and return a result. To do this in Python (and most programming languages), you can use the return statement. Here is a very simple example:

def add(a, b):
    result = a + b
    return result

The above function takes 2 parameters, a and b, it computes the sum of these variables and saves it into a result variable. It then returns this result variable. When you call it, you can assign its return value to a variable like so:

c = add(5, 5)
# here c = 10

d = add(1, 5)
# here d = 6

one = 1
two = 2
f = add(one, two)

g = add(c, d)
# here g = 16

Here you see an example of how a function called add can be used and called multiple times. It can be called directly with values (example c and d) or with existing variables (example f and g)

In Python, a function always returns a value. If you do not explicitly write a return statement in your function definition, Python will add an implicit return None. In other words if a function has not explicit return statement, it will return None.

You can check this by assigning the execution of a function with no implicit return to a variable and printing its value:

def does_nothing():
    pass

nothing = does_nothing()
# here nothing = None

Use case 1: average of a list

Imagine we have a list grades for which we want to compute the average. Here is the code I would use without a function.

grades_1 = [12, 15, 10, 17]

sum  = 0
for grade in grades_1:
    sum += grade
avg = round(sum / len(grades_1), 2)

We are summing all the elements in the list, and then dividing the sum by the length of the list, rounding the result to maximum 2 decimal.

This works, but it is not reusable. If I want to do it again for a different list of grades, for example grades_2 = [18, 15, 11, 13], I would have to copy and paste my code above and tweak it for it to work with the grades_2 variable. However, if I create a function called average, I can reuse it easily on the 2 lists. Let’s do it:

def average(grades):
    sum  = 0
    for grade in grades:
        sum += grade
    avg = round(sum / len(grades), 2)
    return avg

This is the same code as above, just extracted into a function.

Now that we have the function, we can call it or apply it multiple times:

grades_1 = [12, 15, 10, 17]
grades_2 = [18, 15, 11, 13]
avg_1 = average(grades=grades_1)
# here avg_1 = 13.5
avg_2 = average(grades=grades_2)
# here avg_2 = 14.25

Use case 2: formatting a string

Imagine we are given list of names with different formats, and we want all the names to have the same format. For this, we will write a function with converts all the names to title case using the title() string method.

def format(names):
    result = []
    for name in names:
        formatted_name = name.title()
        result.append(formatted_name)
    return result


unformatted_names = ["JANE", "john", "Janet"]
formatted_names = format(names=unformatted_names)
# here formatted_names = ['Jane', 'John', 'Janet']

Here if we are ever given more list of unformatted names, we can reuse our function to format them.

Conclusion

This blog post has just introduced functions, why they are useful in programming and how to define them and call them in Python.

Code

All the code from this blog post can be found in this replit.