Skip to content

Functions

Little Building Blocks

We have figured out how to enable the user to input one parameter of our simulation and also how to make sure that the input value is a positive number. If we now want to do this for the other parameters as well, we might think of copying the code and adapting it a bit. This is however not a good idea.

Dangers of Copy & Paste-Code

Code that is repeated bears the risk of making your program harder to read and maintain. Some common issues that come along with duplicating code are:

  • Forgetting to adapt a part of the copied code
  • Finding all copied segments can be tricky, especially when they need to be updated to changed requirements
  • If the copied code has a subtle bug, the same bug will be replicated multiple times in your code and you need to make sure find all occurences

To circumvent the issues that arise from copying code and to create smaller, self-contained segments, that can be re-used, a function is the way to go. You already encountered functions like print(…) and input(…). Now it is time to write our own.

We will start by providing a function definition at the beginning of our file. This will explain to our computer what this function is about, what its function name is and which parameters have to be provided, so it has all required information to do its work.

Within pairs of three quotes (""" … """) we can add a documentation comment (also known as docstring) to give the reader of the code an idea what this function is about.

Documentation

Code is more often read than written and thus should be easy to grasp and well-documented. The docstring may be omitted in very trivial and obvious cases. If in any doubt: Add a documentation.

def input_positive_integer():  # See note (1)(2)(3)(4)(5)
    """Query the user to input a positive number.

    If the given number was negative, the user is prompted to try again.

    Returns:
        A positive number as given by user input.
    """
    input_was_valid = False
    while not input_was_valid:
        user_input = input("Please input the size of the starting population: ")
        input_as_int = int(user_input)
        input_was_valid = input_as_int >= 0
        if not input_was_valid:
            print("Sorry,", input_as_int, "is not a valid input, please try again")

    return input_as_int  # See note (6)

Let’s take a closer look at the notes:

  1. The def-keyword tells Python that the following is a function definition.
  2. The function name is given as input_positive_integer.
  3. The parameters are listed in parenthesis ( … ). Even if there are no parameters given in this case, the parenthises must be there.
  4. def + function name + parameters form the so-called function head, which is concluded by a colon :
  5. The function head is immediately followed by a docstring.
  6. After the function has finished, all variables used inside are lost. To get a result out of the function, the return-keyword allows to hand back a value that can be assigned to a variable again. Using the return-keyword stops the function right then and there and hands back the value of whatever you return.

More customization

This current function always asks for the starting population, which is a bit unlucky. We would like to be able to customize the function a bit so it can ask for different things. For this purpose we cann add a parameter to the function.

def input_positive_integer(ask_for_what):  # see note (1)(2)
    """Query the user to input a positive number.

    If the given number was negative or 0, the user is prompted to try again.

    Args:
        ask_for_what:
            A text indicating what the user should input the value for.
            It will be used for constructing the prompt that the user
            sees when asked for the input.
    Returns:
        A positive number as given by user input.
    """
    prompt = "Please input the " + ask_for_what + ": "  # See note (3)
     # Loop as before
        user_input = input(prompt)  # See note (3)
     # Rest as before
1. We added a parameter called ask_for_what which we can use later to specify the text that should be included when asking for input. 2. Note that when we add a new parameter to the function it also has to be documented. 3. To make the line for the input request a bit less convoluted we also introduced a variable prompt in which we store the full text of the request that the user gets to see.

Time to Shine!

With our function defined, we can use it by writing down its name, followed by parenthesis with the values for the parameters:

# Note that we do an assignment here to capture the values returned by the function in the respective variables
starting_population = input_positive_integer("starting population")
food_per_day = input_positive_integer("amount of food per day")

The fine print

Using a function is referred to as calling a function. A function must be defined before it can be used. You very often find function definitions at the start of files or in separate files (we will talk about how to do this later).

Key Points

  • Functions can be used to split a program into smaller, independent chunks
  • Functions have a function name and parameters in parenthesis
  • Functions must be defined before they can be called
Code Checkpoint

This is the code that we have so far: