Skip to content

Functions

In this section, you’ll learn to write functions, which are named blocks of code that are designed to do one specific task. If you need to perform that task multiple times throughout your program, you don’t need to type all the code for the same task again and again; you just call the function dedicated to handling that task. By defining functions, your programs will get easier to write, read, test, and fix.

Defining a function

Here’s a simple function named greet_user() that prints a greeting:

def greet_user():
    print("Hello!")

This example shows the simplest structure of a function. With the keyword def we define a function, followed by the name of our function. Within the parentheses we can (optionally) specify any information the function needs to do its job. This information is defined in the form of parameters (more on that later).

Any indented lines that follow def greet_user(): make up the body of the function. The line print("Hello!") is the only line of actual code in the body of this function, so greet_user() has just one job: print("Hello!").

When you want to use a function, you have to call it. To do so, simply write the function name, followed by any required information in parentheses.

# call the function
greet_user()
>>> Output
Hello!

Detour: docstrings

As previously discussed, it is always good practice to add comments to your code in order to improve readability. That applies to functions as well. In case of functions, one can add a docstring, which is essentially a longer comment that describes the function. A docstring is written in triple quotes """...""" and is placed directly after the function definition.

def greet_user():
    """Display a simple greeting."""
    print("Hello!")

Now, you can display the docstring by calling the built-in help() function with the function name as an argument:

help(greet_user)
>>> Output
Help on function greet_user in module __main__:
greet_user()
    Display a simple greeting.

Docstrings facilitate the proper documentation of your code. Most of all, they will help you in the long run to remember what your code does.

Meme

Parameters

After some modification, the function greet_user() should not only tell the user "Hello!" but also greet them by name. Therefore, we have to define a parameter called user_name. Now, each time you call the function, you need to pass a user_name such as "admin" to the function.

def greet_user(user_name):
    """
    Display a simple greeting.
    Pass a string with the user's name.
    """
    print(f"Hello, {user_name}!")

greet_user("admin")
>>> Output
Hello, admin!
Info

As you can see in the example above, a docstring can span multiple lines!

Up until now, the functions had no parameters at all or just a single parameter. However, you can define as many parameters as you like, seperated by a comma (,):

def greet(first_name, last_name):
    print(f"Hello, {first_name} {last_name}!")
Break-even point

Remember the task to calculate the break-even point? Now, you'll wrap following formula within a function: $$ \text{BEP (units)} = \frac{\text{Fixed Costs}}{\text{Price per Unit} - \text{Variable Cost per Unit}} $$

Write a function called calculate_bep() that takes the following parameters:

  • fixed_costs
  • price_per_unit
  • variable_cost_per_unit

Print the calculation result (break-even point) within the function. Call the function with following arguments:

fixed_costs = 30000
price_per_unit = 75
variable_cost_per_unit = 45

Terminology

parameter vs. argument

A parameter is the variable inside the parentheses of the function definition - def greet_user(user_name):. Here user_name is the parameter. When you call the function with, for example greet_user("admin"), the value "admin" is referred to as an argument. You can think of the parameter as a placeholder and the argument as the actual value.

Positional arguments

When you call a function, Python must match each argument in the function call with a parameter in the function definition. The simplest way to do this is based on the order of the arguments provided which is referred to as positional arguments.

def add_numbers(a, b):
    """Add two numbers."""
    print(a + b)

add_numbers(3, 5)
>>> Output
8

Order matters!

You can get unexpected results, if you mix up the order of the arguments in a function call when using positional arguments:

def perform_calculation(a, b):
    """Calculate something."""
    print(a + b**b)

a = 12
b = 5

# correct order
perform_calculation(a, b)
# incorrect order (produces a different result)
perform_calculation(b, a)
>>> Output
3137
8916100448261

Next up, we'll introduce keyword arguments to avoid such mistakes.

Keyword arguments

A keyword argument is a name-value pair that you pass to a function. You directly associate the name and the value within the argument, so when you pass the argument to the function, there’s no confusion.

perform_calculation(a=12, b=5)

#  you can switch the order of the named keyword arguments
perform_calculation(b=5, a=12)

No matter the order, the result is the same!

>>> Output
3137
3137

Default values

When writing a function, you can optionally define a default value for each parameter. If an argument for a parameter is provided in the function call, Python uses the argument value. If not, the parameter’s default value is used. Using default values can simplify your function calls and clarify the ways in which your functions are typically used. Let's look at an example.

def describe_lab(lab_name, lab_supervisor="Miriam"):
    print(f"{lab_name} is supervised by {lab_supervisor}")

# use the default value for lab_supervisor
describe_lab(lab_name="Chemistry")

# provide a value for lab_supervisor
describe_lab(lab_name="IT", lab_supervisor="Alex")
>>> Output
Chemistry is supervised by Miriam
IT is supervised by Alex

Return values

A function doesn’t have to display its output directly with print(). Instead, usually a function executes a task and returns the result. The result, the return value can be of any type. To return a value, use the return statement.

def square_number(number):
    square = number ** 2
    return square

When you call the function, you can assign the result to a variable.

result = square_number(5)
Password check

Write a function to check if a user is able to log-in.

You have to determine if the given username and password (in plain text) are within the database. The database is a dict with IDs as keys and another dict as value, containing username and hashed password.

Given 'database':

very_secure_db = {
    0: {
        "username": "SwiftShark22",
        "password": "ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f",
    },
    1: {
        "username": "FierceFalcon66",
        "password": "07ac6e7d83aa285293fc325fecd04a51e933ab94d43dbc6434ddca652718fb95",
    },
    2: {
        "username": "admin",
        "password": "6feb4c700de1982f91ee7a1b40ca4ded05d155af3987597cb179f430dd60da0b",
    },
    3: {
        "username": "BraveWolf11",
        "password": "c430e4368aff7c1bc75c3865343730500d7c1a5f65758ade56026b08e94686cc",
    },
}

Meme

Use following function to convert a password to its hash:

import hashlib

def hash_password(password):
    return hashlib.sha256(password.encode()).hexdigest()

Now, write a function that takes at least two arguments, username and password (in plain text!). Check if the given username and hashed password are within the very_secure_db. Return True if the user is able to log-in, otherwise False.

Call your function for following users:

user1 = ("SwiftShark22", "password123")
user2 = ("FierceFalcon", "sdkjf34§")
user3 = ("admin", "1b40ca4ded0")
Info

As you have seen in the above example, functions help you to structure your code. For instance, the function hash_password() was reused multiple times (to generate the very_secure_db and within your own function).

Functions also help you to break down complex problems. You can write a function for each subtask and then combine them to solve the problem as a whole.

Recap

This section introduced the concept of functions to better structure your code, make it more readable and reusable. We have covered:

  • How to define a function
  • Docstrings as a tool to document your functions
  • Parameters vs arguments
  • Positional and keyword arguments
  • Defining default values for parameters
  • The return statement
  • How to use functions to solve smaller subtasks and structure your code