Defining Our Own Functions

The built-in functions are useful but pretty generic. Often there aren’t built-in functions that do what we want, such as calculate mileage or play a game of cribbage. When we want functions to do these sorts of things, we have to write them ourselves.

Because we live in Toronto, Canada, we often deal with our neighbor to the south. The United States typically uses Fahrenheit, so we convert from Fahrenheit to Celsius and back a lot. It sure would be nice to be able to do this:

 >>>​​ ​​convert_to_celsius(212)
 100.0
 >>>​​ ​​convert_to_celsius(78.8)
 26.0
 >>>​​ ​​convert_to_celsius(10.4)
 -12.0

However, the function convert_to_celsius doesn’t exist yet, so instead we see this (focus only on the last line of the error message for now):

 >>>​​ ​​convert_to_celsius(212)
 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
 NameError: name 'convert_to_celsius' is not defined

To fix this, we have to write a function definition that tells Python what to do when the function is called.

We’ll go over the syntax of function definitions soon, but we’ll start with an example:

 >>>​​ ​​def​​ ​​convert_to_celsius(fahrenheit):
 ...​​ ​​return​​ ​​(fahrenheit​​ ​​-​​ ​​32)​​ ​​*​​ ​​5​​ ​​/​​ ​​9
 ...

The function body is indented. Here, we indent four spaces, as the Python style guide recommends. If you forget to indent, you get this error:

 >>>​​ ​​def​​ ​​convert_to_celsius(fahrenheit):
 ...​​ ​​return​​ ​​(fahrenheit​​ ​​-​​ ​​32)​​ ​​*​​ ​​5​​ ​​/​​ ​​9
  File "<stdin>", line 2
  return (fahrenheit - 32) * 5 / 9
  ^
 IndentationError: expected an indented block

Now that we’ve defined function convert_to_celsius, our earlier function calls will work. We can even use built-in function help on it:

 >>>​​ ​​help(convert_to_celsius)
 Help on function convert_to_celsius in module __main__:
 
 convert_to_celsius(fahrenheit)

This shows the first line of the function definition, which we call the function header. (Later in this chapter, we’ll show you how to add more help documentation to a function.)

Here is a quick overview of how Python executes the following code:

 >>>​​ ​​def​​ ​​convert_to_celsius(fahrenheit):
 ...​​ ​​return​​ ​​(fahrenheit​​ ​​-​​ ​​32)​​ ​​*​​ ​​5​​ ​​/​​ ​​9
 ...
 >>>​​ ​​convert_to_celsius(80)
 26.666666666666668
  1. Python executes the function definition, which creates the function object (but doesn’t execute it yet).

  2. Next, Python executes function call convert_to_celsius(80). To do this, it assigns 80 to fahrenheit (which is a variable). For the duration of this function call, fahrenheit refers to 80.

  3. Python now executes the return statement. fahrenheit refers to 80, so the expression that appears after return is equivalent to (80 - 32) * 5 / 9. When Python evaluates that expression, 26.666666666666668 is produced. We use the word return to tell Python what value to produce as the result of the function call, so the result of calling convert_to_celsius(80) is 26.666666666666668.

  4. Once Python has finished executing the function call, it returns to the place where the function was originally called.

Here is an image showing this sequence:

images/functions/def_call.png

A function definition is a kind of Python statement. The general form of a function definition is as follows:

 def​ function_name(parameters):
  block

The function header (that’s the first line of the function definition) starts with def, followed by the name of the function, then a comma-separated list of parameters within parentheses, and then a colon. A parameter is a variable.

You can’t have two functions with the same name in the same file; it isn’t an error, but if you do it, the second function definition replaces the first one, much like assigning a value to a variable a second time replaces the first value.

Below the function header and indented (four spaces, as per Python’s style guide) is a block of statements called the function body. The function body must contain at least one statement.

Most function definitions will include a return statement that, when executed, ends the function and produces a value. The general form of a return statement is as follows:

 return​ expression

When Python executes a return statement, it evaluates the expression and then produces the result of that expression as the result of the function call.