Writing Functions#

Learning Objectives

Questions:

  • How can I create my own functions?

Objectives:

  • Explain and identify the difference between function definition and function call.

  • Write a function that takes a small, fixed number of arguments and produces a single result.

  • Identify local and global variables.


What are functions?#

In Python, a function is like a little machine in your code: you give it a name, tell it what steps to perform, and then you can use it whenever you need that task done. Instead of copying and pasting the same code over and over, you can just “call” the function and let it do the work for you. This makes your programs shorter, easier to read, and much simpler to update.

You have already met some of Python’s built-in functions - things like print(), type(), and len(). Both functions and methods are recognized by their name followed by parentheses (), which is how you call them to perform an action.

Built-in functions are great, but sometimes you might want something that is made just for your program. That is where user-defined functions come in - you can create your own!

Here are a few key things to know about functions:

  • A function is a block of code that only runs when you call it.

  • Once defined, you can reuse it as many times as you like without rewriting the code.

  • You can send information into a function - these are called parameters.

  • A function can give something back - this is called its return value.

Use functions to make your code easier to understand#

Human beings can only keep a few items in working memory at a time. But we can work with larger and more complicated ideas by breaking content down into pieces. Functions serve a similar purpose in Python. We can create our own functions to encapsulate complexity and treat specific actions or ideas as a single “thing”. Functions also enable us to re-use code so we can write code one time, but use it many times.


Defining a function#

You define a function using def with a name, parameters, and a block of code.

Begin each definition of a new function with the keyword def (for “define”), followed by the name of the function. Function names follow the same rules as variable names.
Next, add your parameters in parentheses. You should still use empty parentheses if the function does not take any inputs.
Finally, like in conditionals and loops, you will add a colon and an indented block of code that will contain the body of your function.

def print_greeting():
    print('Hello!')

Defining a function does not run it#

Note that we do not have any output when we run code to define a function. This is similar to assigning a value to a variable. The function definition is sort of like a recipe in a cookbook - the recipe does not create a meal until we use it. So we need to “call” a function to execute the code it contains. This means that Python will not show you errors in your function until you call it. So when a definition of a function runs without error it does not mean that there will not be errors when it executes later.

print_greeting()

Hide code cell output

Hello!

Matching arguments and parameters#

Functions are most powerful when they can take in data.

  • Parameters are names you list in the function definition. They act like placeholders.

  • Arguments are the actual values you pass in when calling the function.

Python matches arguments to parameters by position (or by name).
This means:

  • If a function defines a parameter, you must provide a matching argument when you call it (unless the parameter has a default value).

  • If you pass an argument that has no corresponding parameter, Python will raise an error.

  • Likewise, if a parameter is required but you do not provide an argument, you will also get an error.

In other words, parameters and arguments must match: you can only use data inside a function if there is a parameter defined for it, and you must give an argument for every parameter that requires one.

def print_named_greeting(name):
    print(f'Hello {name}!')

print_named_greeting('World')

Hide code cell output

Hello World!

To expand on the recipe metaphor above, the arguments you add to the () contain the ingredients for the function, while the body contains the recipe.

Functions with defined parameters will result in an error if they are called without passing an argument:

print_named_greeting()

Hide code cell output

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 print_named_greeting()

TypeError: print_named_greeting() missing 1 required positional argument: 'name'

Use return to pass values back from a function#

In the date example above, we printed the results of the function code to output, but there are better way to handle data and objects created within a function. We can use the keyword return to send a value back to the “global” environment. (We will learn about local and global variables below). A return command can occur anywhere in the function, but is often placed at the very end of a function with the final result.

def calc_fine(days_overdue):
    if days_overdue <= 10:
        fine = days_overdue * 0.25
    else:
        fine = (10 * 0.25) + ((days_overdue - 10) * 0.75)
    return fine

fine = calc_fine(12)
print(f"Fine owed: ${fine}")

Hide code cell output

Fine owed: $4.0

A function that does not explicitly return a value will automatically return None.

result = print_named_greeting('World')
print(f'result of call is: {result}')

Hide code cell output

Hello World!
result of call is: None

Variable scope#

When we define a variable inside of a function in Python, it is known as a local variable, which means that it is not visible to – or known by – the rest of the program. Variables that we define outside of functions are global and are therefore visible throughout the program, including from within other functions. The part of a program in which a variable is visible is called its scope.

This is helpful for people using or writing functions, because they do not need to worry about repeating variable names that have been created elsewhere in the program.

initial_fine = 0.25
late_fine = 0.75

def calc_fine(days_overdue):
    if days_overdue <= 10:
        fine = days_overdue * initial_fine
    else:
        fine = (10 * initial_fine) + ((days_overdue - 10) * late_fine)
    return fine
  • initial_fine and late_fine are global variables.

  • days_overdue is a local variable in calc_fine. Note that a function parameter is a variable that is automatically assigned a value when the function is called and so acts as a local variable.

  • fine is also a local variable, created inside the function to hold the calculated result.

fine = calc_fine(12)
print(f'Fine owed: ${fine:.2f}')
print(f'Fine rates: ${initial_fine:.2f}, ${late_fine:.2f}')

Hide code cell output

Fine owed: $4.00
Fine rates: $0.25, $0.75
print(f'Days overdue: {days_overdue}')

Hide code cell output

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 print(f'Days overdue: {days_overdue}')

NameError: name 'days_overdue' is not defined

Use docstrings to provide online help#

If the first thing in a function is a string that is not assigned to a variable, that string is attached to the function as its documentation. This kind of documentation at the beginning of a function is called a docstring.

def fahr_to_celsius(temp):
    "Input a fahrenheit temperature and return the value in celsius"
    return ((temp - 32) * (5/9))

This is helpful because we can now ask Python’s built-in help system to show us the documentation for the function:

help(fahr_to_celsius)

Hide code cell output

Help on function fahr_to_celsius in module __main__:

fahr_to_celsius(temp)
    Input a fahrenheit temperature and return the value in celsius

We do not need to use triple quotes when we write a docstring, but if we do, we can break the string across multiple lines:

def fahr_to_celsius(temp):
    """Convert fahrenheit values to celsius
    Input a value in fahrenheit
    Output a value in celsius"""
    return ((temp - 32) * (5/9))
help(fahr_to_celsius)

Hide code cell output

Help on function fahr_to_celsius in module __main__:

fahr_to_celsius(temp)
    Convert fahrenheit values to celsius
    Input a value in fahrenheit
    Output a value in celsius

Exercises#

Exercise 1: Create a function#

Write a function called addition that takes two parameters and returns their sum. After defining the function, call it with several arguments and print out the results.


Exercise 2: Conditional statements within functions#

Create a function called grade_converter that takes a numerical score (0 - 100) as its parameter and returns a letter grade based on the score:

  • 90 and above returns ‘A’

  • 80 to 89 returns ‘B’

  • 70 to 79 returns ‘C’

  • 60 to 69 returns ‘D’

  • Below 60 returns ‘F’

After defining the function, test it using different scores.


Exercise 3: Local and global variables#

List all of the global variables and all of the local variables in the following code.

fine_rate = 0.25

def fine(days_overdue):
    if days_overdue <= 10:
        fine =  days_overdue * fine_rate
    else:
        fine = (days_overdue * fine_rate) + ((days_overdue - 10) * (fine_rate*2))
    return fine
    
total_fine = calc_fine(20)
f'Fine owed: ${total_fine:.2f}'
'Fine owed: $15.00'

Key points#

  • Break programs down into functions to make them easier to understand.

  • Define a function using def with a name, parameters, and a block of code.

  • Defining a function does not run it.

  • Arguments in call are matched to parameters in definition.

  • Functions may return a result to their caller using return.