Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Functions

Learning outcomes

Prerequisites

Application and syntax

At this stage, we should be able to accomplish quite a lot with a Python program. We can see how, as the tasks become more complex, our programs become longer and more repetitive. This makes code more tedious to write and very hard to read or edit.

Thankfully, there is a key building block which can help us organise our code in a more logical way: the function. We have encountered functions already. Every time we have used a keyword followed by parentheses (), we have been using a function, as with print("Hello"), math.sqrt(2) or molecules.append("H2O"). In this lesson, we will learn how to define our own functions.

A function is an isolated capsule of code where some values are fed in, an operation is carried out, and new values are fed out. Here is the generic syntax:

def function_name(an_argument):
    Code block, e.g. doing maths on an_argument
    return an_output

Once a function is defined, later in the code, it can be executed by writing its name and inserting any arguments it requires between parentheses. Following the naming above:

result = function_name(new_argument)

Note that we can call this function as many times as we want, with different arguments, and they don’t need to be called the same. In the function definition, an_argument is a placeholder name, by which we will refer to the inputs in the function body.

Let’s look at a real example:

def atomic_masses_sum(atom_masses):
    """
    Sum all the atomic masses together and return the result.

    Arguments
    ---------
    atom_masses : list of floats
        The masses to be summed.
    
    Returns
    -------
    total_mass : float
        The sum of atomic masses.

    """
    total_mass = 0
    for atom_mass in atom_masses:
        total_mass = total_mass + atom_mass

    return total_mass

water_atomic_masses = [1.008, 1.008, 15.999]
water_total_mass = atomic_masses_sum(water_atomic_masses)

print(f"The total mass of water is {water_total_mass} u.")

Note that:

Try changing the masses in water_atomic_masses and ensure that the result is as you would expect.

Solution
def atomic_masses_sum(atom_masses):
    """
    Sum all the atomic masses in atomic massunits together and return the result in grams.

    Arguments
    ---------
    atom_masses : list of floats
        The masses to be summed in u.
    
    Returns
    -------
    total_mass : float
        The sum of atomic masses in g.

    """
    total_mass = 0
    conversion_u_to_g = 1.66054e-24
    for atom_mass in atom_masses:
        total_mass = total_mass + atom_mass

    # convert to g
    total_mass = total_mass * conversion_u_to_g

    return total_mass

water_atomic_masses = [1.008, 1.008, 15.999]
water_total_mass = atomic_masses_sum(water_atomic_masses)

print(f"The total mass of water is {water_total_mass} g.")

The key is to make sure that the conversion happens within the function body, so it must be indented. Note how the docstrings were also updated. Previously, the function was unit agnostic, but now it only works properly if we input a particular unit.

It’s very important to write good documentation for your code (either as a docstring or as a manual), because using this function incorrectly would return a result without raising an error. It’s also possible to write checks within the function to make sure that the input is sensible, but this adds complexity and should only be used as a failsafe to good documentation and useability.

Solution
This is another classic beginner programmer problem.
def is_even(num):
    """
    Check if a number is even.

    Arguments
    ---------
    num : int
        Number to check
    Returns
    -------
    check: bool
        True if num is even, False otherwise
    
    """
    if num % 2 == 0:
        check = True
    else:
        check = False
    return check

# testing
print(is_even(9))
print(is_even(42))

An even number has no remainder when divided by 2, so we can use % 2 to check the remainder of this division and classify the number.

Once the function is in place, we can check the parity of a number with a single line, instead of needing to write the five lines of code inside the function every time.

Summary