Search
Functions

Prerequisites

  • Types
  • Collections

Functions

Occasionally, there is a particular piece of code that you would like to reuse over-and-over, without having to write the code over-and-over). For this case, Python allows the use of functions, these are segments of code to which arguments are passed and some operation is performed on them. You will have already encountered some examples of functions, such as print() and type(). However, in this section we will introduce how custom functions can be written for your code. A function can be easily recognised in Python as it is some statement followed immediately by a set of brackets (which contain the arugments).

The general syntax for defining a function is Python is as follows,

def kinetic_energy(mass, velocity):
    """
    Determine the kinetic energy of a particle.
    
    Args:
        mass (float): Particle mass (kg)
        velocity (float): Particle velocity (m/s)
        
    Returns:
        (float): Particle kinetic energy (J)
    """
    kinetic_energy = 0.5 * mass * velocity ** 2
    return kinetic_energy

Above, the function has been given the name kinetic_energy and takes two arguments; mass and velocity, the kinetic energy is then found and returned.

Following definition, the function may be used as follows,

print(kinetic_energy(10, 300))
450000.0

The function above has been called with the variables mass=10 and velocity=30. Within the function, the following steps are occuring,

>>> kinetic_energy = 0.5 * mass * velocity ** 2
>>> kinetic_energy = 0.5 * 10 * 300 ** 2
>>> kinetic_energy = 450000.0

>>> return kinetic_energy
>>> return 450000.0

The kinetic energy value then returned by the function, and in the case above passed to the print() function. Hence, it is printed to the screen.

Defining a function

Having seen, generally, how functions work, let's go into a bit more detail of function declaration,


Figure 1. The anatomy of a simple Python function.

The function consists of four main textual areas:

  • Definition: Beginning with def, this is where the name and arguments for the function are defined
  • Docstring: This contains information about what the particular function does, including the arguments and what is returned
  • Content: Where the code of the function lives
  • Return: The information that is returned from the function, using the return keyword.



Aside: whitespace

Python takes whitespace seriously. It is used for idenifying a block; such as a function. The function content begins when the indented section starts and ends when the indentation is removed. In Figure 1, the docstring, content and return of the function are all within this block, if the whitespace is removed then Python will consider the function to be completed at this point. The indentation can be any length (although 4 spaces is a PEP8 Standard) but needs to be consistent. Throughout this book, we will see a few examples of other blocks (such as loops and if-statement), when you come across these note the importance of the whitespace that is used to define the block.



Definition

A function is defined using the keyword def, which tells the Python interperator that in that line you will be giving a function name followed by a set of brackets, some arguments (although these are not essential), and a colon. The function name needs to be a single continuous string of characters with no whitespace between them, a common convention is to use the _ (underscore) character to denote where there should be a space. Note, kinetic_energy above.

The number of arguments that a function may have can be anything from 0 to infinity (although that is obviously impractical). If a function is to have no arguments, it will simply have the open and closed brackets immediately following the function definition with nothing inside them.

In addition to arguments, a function may also have keyword arguments. These are arguments that are defined with a default value which may be changed when the function is called. An example of this is shown below,

def beer_lambert(epsilon, absorbance, path_length=1.):
    """
    Evaluate the concentration of a solution, using the Beer-Lambert law.
    
    Args:
        epsilon (float): Molar attenuation coefficient (L/(mol cm))
        absorbance (float): Absorbance of the solution
        path_lenght (float, optional): Distance travelled through the sample (cm).
    
    Returns:
        (float): Concentration of solution (mol/L)
    """
    concentration = absorbance / (epsilon * path_length)
    return concentration

In the Beer-Lambert law function above, the path length is assumed to be 1 cm if no other value is given (this is because most spectroscopic curvettes are 1 cm wide). This means that there are now, two possible way to run the function above.

If the path length is 1 cm, the following is run,

print(beer_lambert(21000, 200))
0.009523809523809525

Else the path length is some other value (in the example below 10 cm), then the following is run.

print(beer_lambert(21000, 200, path_length=10))
0.0009523809523809524

While it makes the code clearer, the path_length keyword does not need to be included, so the following will also run,

print(beer_lambert(21000, 200, 10))
0.0009523809523809524

Docstring

The docstring is an important (although not essential) component of any function. Describing the purpose of a function is valuable of many reasons, it helps to clarify what the function will do, it offers guidence for others on how to use the function, and it acts to remind future you why it is that you have a particular function and what is does. You may read this last point and roll your eyes, however I promise you that code you write today will not stay present in your memory forever.

In addition to a description of the function, a docstring also typically includes information about the arguments taken by the function and objects that are returned. There are a few common way that these may be formatted, within this book we will use Google Style, however, other styles exist, such as NumPy and Sphinx. Using a standard style of docstring is useful when writting large software packages, due to the availablity of tools to automatically generate software documentation from these docstrings. The Google style indicates the arguments with the keyword Args, before listing the arguments, the expected type and a short description (we find that it can be helpful to include information about the expected units in this section). The Returns keyword is followed by a list of the values returned by the function, since these do not necessary has a name this is omitted.

Content

The content of the function is relatively straightforward, it is the code that means the function does something. However, this is a good chance to mention scope, the scope of a variable is the area in the code that it can be used. A variable that is created inside a function cannot be used elsewhere in your program, this includes the arugment variables. However, it is possible to make use of a variable defined outside of a function within it, just remember that a piece of Python code is parsed from top-to-bottom so the variable needs to be defined before the function. See below for an example of this in action,

speed_of_light = 2.99792458e8
planck = 6.62607004e-34

def photon_energy(wavelength):
    """
    Determines the energy of a single photon with a given wavelength.
    
    Args:
        wavelength (float): Photon wavelength (m)
    
    Returns:
        (float): Photon energy (J)
    """
    return planck * speed_of_light / wavelength
print(photon_energy(600e-9))
3.310743040286264e-19

Return

The return statement is the keyword that tells the Python interpertor to stop the function and return the value(s) given. You will note in the photon_energy() function above, there is a mathematical operation on the return line. This is fine as the mathematics will be carried out before the value is returned.

It is possible return more than one variable from a function. These will be returned as a tuple of variables, which may require unpacking as appropriate. An example where more than one variable is returned is shown below,

speed_of_light = 2.99792458e8
planck = 6.62607004e-34

def photon_energy(wavelength):
    """
    Determines the energy of a single photon with a given wavelength in both
    Joules and electron volts.
    
    Args:
        wavelength (float): Photon wavelength (m)
    
    Returns:
        (tuple of length 2, float): Photon energy in J and eV respectively
    """
    energy = planck * speed_of_light / wavelength
    return energy, energy * 6.242e+18
print(photon_energy(600e-9))
(3.310743040286264e-19, 2.066565805746686)

The function kinetic_energy, introduced earlier, calculates the kinetic energy given the mass and velocity of a particle.

Exercise: Write a function that returns the momentum of a particle given the particle's mass and velocity. Recall that

$$ p = mv. $$

Following this write another function that uses this momentum to calculate the kinetic energy of the particle using

$$ E_{kin} = \frac{p^{2}}{2m}. $$

Check your kinetic energy function using the kinetic_energy function. Ensure that your functions have appropriate docstrings so that other users can use your functions.

### Write your code here