8. Creating Functions¶
8.1. Creating Simple Functions¶
Defining a function is rather easy.
- Start with the keyword
def, which is short for “define.”
- Next, give the function a name. There are rules for function names. They must:
- Start with a lower case letter.
- After the first letter, only use letters, numbers, and underscores.
- Spaces are not allowed. Use underscores instead.
- While upper-case letters can be used, function names are normally all lower-case.
- After that, we have a set of parenthesis. Inside the parenthesis will go parameters. We’ll explain those in a bit.
- Next, a colon.
- Everything that is part of the function will be indented four spaces.
- Usually we start a function with a multi-line comment that explains what the function does.
Function definitions go below the
import statements, and above the
rest of the program. While you can put them somewhere else, you shouldn’t.
Below is a program that defines and uses the function twice.
1 2 3 4 5 6 7
def print_hello(): """ This is a comment that describes the function. """ print("Hello!") print_hello() print_hello()
You can define and use multiple functions. But all function definitions should go before the main code.
1 2 3 4 5 6 7 8 9 10
def print_hello(): print("Hello!") def print_goodbye(): print("Bye!") print_hello() print_goodbye()
Actually, almost all code should go in a function. It is a good practice
to put the main starting point of your program in a function called
and call it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
def print_hello(): print("Hello!") def print_goodbye(): print("Bye!") def main(): """ This is my main program function """ print_hello() print_goodbye() # Run the main program main()
An even better way of writing this is with a check to make sure we are trying to run this file, and not import it. The statement for this looks a little weird. In fact, it is weird enough I just look it up and copy/paste it any time I want to use it. Don’t worry about understanding how it works yet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
def print_hello(): print("Hello!") def print_goodbye(): print("Bye!") def main(): print_hello() print_goodbye() # Only run the main function if we are running this file. Don't run it # if we are importing this file. if __name__ == "__main__": main()
8.2. Taking In Data¶
Functions are even more powerful if we have them take in data.
Here is a simple example that will take in a number and print it. Notice how
I’ve created a new variable
my_number in between the parenthesis. This
variable will be given whatever value is passed in. In the example below, it
is given first a
25, and finally a
1 2 3 4 5 6 7
def print_number(my_number): print(my_number) print_number(55) print_number(25) print_number(8)
You can pass in multiple numbers, just separate them with a comma.
1 2 3 4 5
def add_numbers(a, b): print(a + b) add_numbers(11, 7)
Occasionally, new programmers want to set the number values inside the function. This is wrong. Then the function would only work for those values. The power is in specifying the numbers outside the function. We don’t want the function to be limited to only certain data values.
1 2 3 4 5 6 7 8
# This is wrong def add_numbers(a, b): a = 11 b = 7 print(a + b) add_numbers(11, 7)
8.3. Returning and Capturing Values¶
Functions can not only take in values, functions can return values.
8.3.1. Returning values¶
Function that returns two numbers added together
1 2 3 4
# Add two numbers and return the results def sum_two_numbers(a, b): result = a + b return result
Note: Return is not a function, and does not use parentheses. Don’t do
This only gets us half-way there. Because if we call the function now, not much happens. The numbers get added. They get returned to us. But we do nothing with the result.
# This doesn't do much, because we don't capture the result sum_two_numbers(22, 15)
8.3.2. Capturing Returned Values¶
We need to capture the result. We do that by setting a variable equal to the value the function returned:
# Capture the function's result into a variable # by putting "my_result =" in front of it. # (Use whatever variable name best describes the data, # don't blindly use 'my_result' for everything.) my_result = sum_two_numbers(22, 15) # <--- This line CAPTURES the return value # Now that I captured the result, print it. print(my_result) # <--- This is printing, NOT capturing.
Now the result isn’t lost. It is stored in my_result which we can print or use some other way.
8.3.3. Volume Cylinder Example¶
Function that returns the volume of a cylinder
1 2 3 4
def volume_cylinder(radius, height): pi = 3.141592653589 volume = pi * radius ** 2 * height return volume
Because of the return, this function could be used later on as part of an equation to calculate the volume of a six-pack like this:
six_pack_volume = volume_cylinder(2.5, 5) * 6
The value returned from volume_cylinder goes into the equation and is multiplied by six.
There is a big difference between a function that prints a value and a function that returns a value. Look at the code below and try it out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
# Function that prints the result def sum_print(a, b): result = a + b print(result) # Function that returns the results def sum_return(a, b): result = a + b return result # This prints the sum of 4+4 sum_print(4, 4) # This does not sum_return(4, 4) # This will not set x1 to the sum # It actually gets a value of 'None' x1 = sum_print(4, 4) print("x1 =", x1) # This will set x2 to the sum # and print it properly x2 = sum_return(4, 4) print("x2 =", x2)
When first working with functions it is not unusual to get stuck looking at code like this:
def calculate_average(a, b): """ Calculate an average of two numbers """ result = (a + b) / 2 return result # Pretend you have some code here x = 45 y = 56 # Wait, how do I print the result of this? calculate_average(x, y)
How do we print the result of calculate_average? The program can’t print result because that variable only exists inside the function. Instead, use a variable to capture the result:
def calculate_average(a, b): """ Calculate an average of two numbers """ result = (a + b) / 2 return result # Pretend you have some code here x = 45 y = 56 average = calculate_average(x, y) print(average)
8.4. Documenting Functions¶
Functions in Python typically have a comment as the first statement of the function. This comment is delimited using three double quotes, and is called a docstring. A function may look like:
def volume_cylinder(radius, height): """Returns volume of a cylinder given radius, height.""" pi = 3.141592653589 volume = pi * radius ** 2 * height return volume
The great thing about using docstrings in functions is that the comment can be pulled out and put into a website documenting your code using a tool like Sphinx. Most languages have similar tools that can help make documenting your code a breeze. This can save a lot of time as you start working on larger programs.
8.5. Variable Scope¶
The use of functions introduces the concept of scope. Scope is where in the code a variable is “alive” and can be accessed. For example, look at the code below:
# Define a simple function that sets # x equal to 22 def f(): x = 22 # Call the function f() # This fails, x only exists in f() print(x)
The last line will generate an error because x only exists inside of the f()
function. The variable is created when
f() is called and the memory it uses is
freed as soon as
Here’s where it gets complicated.
A more confusing rule is accessing variables created outside of the
function. In the following code, x is created before the
f() function, and
thus can be read from inside the
# Create the x variable and set to 44 x = 44 # Define a simple function that prints x def f(): print(x) # Call the function f()
Variables created ahead of a function may be read inside of the function only if the function does not change the value. This code, very similar to the code above, will fail. The computer will claim it doesn’t know what x is.
# Create the x variable and set to 44 x = 44 # Define a simple function that prints x def f(): x += 1 print(x) # Call the function f()
Other languages have more complex rules around the creation of variables and scope than Python does. Because Python is straight-forward it is a good introductory language.
Functions pass their values by creating a copy of the original. For example:
# Define a simple function that prints x def f(x): x += 1 print(x) # Set y y = 10 # Call the function f(y) # Print y to see if it changed print(y)
The value of y does not change, even though the f() function increases the value passed to it. Each of the variables listed as a parameter in a function is a brand new variable. The value of that variable is copied from where it is called.
This is reasonably straight forward in the prior example. Where it gets confusing is if both the code that calls the function and the function itself have variables named the same. The code below is identical to the prior listing, but rather than use y it uses x.
# Define a simple function that prints x def f(x): x += 1 print(x) # Set x x = 10 # Call the function f(x) # Print x to see if it changed print(x)
The output is the same as the program that uses y. Even though both the function and the surrounding code use x for a variable name, there are actually two different variables. There is the variable x that exists inside of the function, and a different variable x that exists outside the function.
8.7. Functions Calling Functions¶
For each of the examples below, think about what would print. Check to see if you are right. If you didn’t guess correctly, spend to the time to understand why.
8.7.1. Example 1¶
In this example, note that if you don’t use a function, it doesn’t run.
# Example 1 def a(): print("A") def b(): print("B") def c(): print("C") a()
8.7.2. Example 2¶
# Example 2 def a(): b() print("A") def b(): c() print("B") def c(): print("C") a()
8.7.3. Example 3¶
# Example 3 def a(): print("A") b() def b(): print("B") c() def c(): print("C") a()
8.7.4. Example 4¶
# Example 4 def a(): print("A start") b() print("A end") def b(): print("B start") c() print("B end") def c(): print("C start and end") a()
8.7.5. Example 5¶
# Example 5 def a(x): print("A start, x =", x) b(x + 1) print("A end, x =", x) def b(x): print("B start, x =", x) c(x + 1) print("B end, x =", x) def c(x): print("C start and end, x =", x) a(5)
8.7.6. Example 6¶
While line 3 of this example increases
x variable in the function is a different variable than the
x that is in the rest of the program. So that
x never changes.
# Example 6 def a(x): x = x + 1 x = 3 a(x) print(x)
8.7.7. Example 7¶
This example is similar to the prior example, but we
return x at the end. Turns out, it doesn’t matter. Because we
never do anything with the return value. So the global variable
x still doesn’t increase. See the next example.
# Example 7 def a(x): x = x + 1 return x x = 3 a(x) print(x)
8.7.8. Example 8¶
This example take the value returned from
a and stores it back into
x. How? By doing
x = a(x) instead of
# Example 8 def a(x): x = x + 1 return x x = 3 x = a(x) print(x)
8.7.9. Example 9¶
# Example 9 def a(x, y): x = x + 1 y = y + 1 print(x, y) x = 10 y = 20 a(y, x)
8.7.10. Example 10¶
While you can have two
return statements in a function, once you hit the first
return the function ends. In
return y never runs, because we already returned from the function in the prior line.
# Example 10 def a(x, y): x = x + 1 y = y + 1 return x return y x = 10 y = 20 z = a(x, y) print(z)
8.7.11. Example 11¶
This is not something you can do in every programming language. You can return two values by using a comma and listing them.
# Example 11 def a(x, y): x = x + 1 y = y + 1 return x, y x = 10 y = 20 z = a(x, y) print(z)
8.7.12. Example 12¶
If you return two values out of a function, you can capture them this way.
# Example 12 def a(x, y): x = x + 1 y = y + 1 return x, y x = 10 y = 20 x2, y2 = a(x, y) # Most computer languages don't support this print(x2) print(y2)
8.7.13. Example 13¶
# Example 13 def a(my_data): print("function a, my_data = ", my_data) my_data = 20 print("function a, my_data = ", my_data) my_data = 10 print("global scope, my_data =", my_data) a(my_data) print("global scope, my_data =", my_data)
8.7.14. Example 14¶
We will talk more about these next two examples when we talk about “lists” and “classes” later. These examples don’t operate like you might expect at first. Take a look and see what is different. We’ll explain why it works differently later.
# Example 14 def a(my_list): print("function a, list = ", my_list) my_list = [10, 20, 30] print("function a, list = ", my_list) my_list = [5, 2, 4] print("global scope, list =", my_list) a(my_list) print("global scope, list =", my_list)
8.7.15. Example 15¶
# Example 15 # New concept! # Covered in more detail in a later chapter def a(my_list): print("function a, list = ", my_list) my_list = 1000 print("function a, list = ", my_list) my_list = [5, 2, 4] print("global scope, list =", my_list) a(my_list) print("global scope, list =", my_list)