Functions

Functions are blocks of code that you give a name to that can then be easily run as a whole whenever you need that task performed. They can receive additional information to help with their task, and can return a result containing the information they generate. Writing functions lets us effectivly create our own Python commands that we can then use else where in our programs.

The easiest way to get an idea of functions is through a couple of simple examples. You are probably familiar with the concept of functions in math, so lets return to how we started this entire handbook by doing a little math (only a little I promise).

Hopefully you are comfortable with the following two math formulas:

Obviously these are fairly simple formula such that you may not bother making functions for them, but it will allow the point to be demonstrated nicely.

def area(radius):
    PI = 3.1415
    area = 2 * PI * radius ** 2
    return area

def circumference(radius):
    PI = 3.1415
    circ = 2 * PI * radius
    return circ

r = int(input("What is the radius of your circle?"))
answer = area(r)
print("The area of your circle is: ",answer)
answer = circumference(r)
print("The circumference of your circle is: ",answer)

A few things to point out:

Functions are very useful for separating common tasks out from your main code. It allows you to avoid repeating yourself all the time which makes your code easier to maintain. Tasks like reading from a file, saving to a file, etc are all ideally suited to being chopped off into a separate function. If you’ve worked through the PyGame lessons, you’ve used some functions I’ve created before without fully appreciating what was going on, for instance in the lesson on sprite maps.

Putting functions in separate files

To further help make your code easier to maintain, you can even move all your functions into separate files so they don’t clutter up your main project file (like I used with the sprite map). To do this, you add either a from ... import ... or an import ... at the top of your main project file. Using the previous example, if the circle functions were saved in a file circles.py, it would work like this:

#### File: circles.py

def area(radius):
    PI = 3.1415
    area = 2 * PI * radius ** 2
    return area

def circumference(radius):
    PI = 3.1415
    circ = 2 * PI * radius
    return circ

Method 1

#### File: main.py

from circles import *  # From the circles file, import everything

r = int(input("What is the radius of your circle?"))
answer = area(r)
print("The area of your circle is: ",answer)
answer = circumference(r)
print("The circumference of your circle is: ",answer)

The second method is generally considered better by programmers as it ensures the names of your functions won’t clash with anything in your “main” program. To illustrate the problem with the first method, what would happen if you had a squares.py and a triangles.py file you were also importing which also had functions called area()? Python wouldn’t know which one to use. Method 2 solves that problem.

Method 2

#### File: main.py

import circles   # Import the circles file, requiring the use of "circles." to access its content
r = int(input("What is the radius of your circle?"))
answer = circles.area(r)
print("The area of your circle is: ",answer)
answer = circles.circumference(r)
print("The circumference of your circle is: ",answer)

Named parameters

A parameter is the name given to the values we put into the function when we run it. Our previous exercises just had one parameter, radius. What happens if we need more than one? Easy, we just comma separate them.

File: cylindars.py

#### File: cylinders.py
PI = 3.1415

def surface_area(radius, height):
    sa = 2 * PI * radius**2 + 2 * PI * radius * height
    return sa

def volume(radius, height):
    v = PI * radius ** 2 * height
    return v
#### File: main.py
import cylinders

print("Cylinders calculator")
r = int(input("Radius? "))
h = int(input("Height? "))

answer = cylinders.surface_area(r,h)
print("Surface area: "+str(answer))

answer = cylinders.volume(r,h)
print("Volume: "+str(answer))

What happens if we have so many parameters or functions we can’t remember the order in which they are required? For instance “Was it radius first then height, or height first then radius?”. Putting aside the fact that it’s easy to check and you should have good documentation to refer to… there is also another way: you can name your parameters when passing them in from main. Using the above example, we could change the file main.py to the following.


import cylinders

print("Cylinders calculator")
r = int(input("Radius? "))
h = int(input("Height? "))

answer = cylinders.surface_area(height=h, radius=r)
print("Surface area: "+str(answer))

answer = cylinders.volume(radius=r, height=h)
print("Volume: "+str(answer))

Default and optional parameters

The final important thing to appreciate with functions is that you can decide that some parameters are optional, and work with a default value for them if they aren’t provided. The following example will make family_name an optional parameter.

# Providing a family_name is optional in this example

def greetings( given_name, family_name=None ):
    if family_name:
        print("Hello "+given_name+" "+family_name)
    else:
        print("Hello "+given_name)
# In this example, if family_name is not provided, it will assume you are "Smith"

def greetings( given_name, family_name="Smith" ):
    print("Hello "+given_name+" "+family_name)

In both cases, the following are all valid ways of calling the function from your main file:

greetings("Jane", "Doe")
greetings("Jane")
greetings( given_name="Jane" )
greetings( given_name="Jane", family_name="Doe" )