Python/Tutorial/Functions/Defining a Function

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Introduction

Functions bring code together into one group.

Functions are probably the most important element in Python. The code you write will likely be 99% function definitions, with a little bit of variable definitions.

Function Template

The function template is as follows:

def name(parameters):
    """doc string"""
    body

The name is the name of the function. It is also the variable that the function will be stored at after the function is defined.

The parameters list how many parameters the function accepts, and what their names are.

The doc string is a descriptive string that describes the function. This is optional, but I strongly encourage you to specify one for every function that you write. The description should include a description of what the parameters mean and what the function returns.

The body is the code that the function runs when it is called.

Function Name

Remember how you can reassign values? You can do the same with the function name. However, the name of the function as it was originally defined is not lost, even though the name you use to refer to the function may be different.

When thinking of the name, think of Python doing two different things when it sees a "def" statement that defines a new function.

  • Create this new thing that is a function, and name it with the function's name that was in the code.
  • Assign the variable with the same name the the value of the function.

You can subsequently assign other variables to refer to the same function, or even assign the variable with the same name as the function to be something else later on.

Yes, this is confusing, but it's the good kind of confusing. As long as you don't fight it, it won't bite you. In fact, it may even give you foot massages after a long day's work.

Function Parameters

We're going to dig into what sorts of magic are available for the parameters of a function. For now, it's simply a list of names, separated by commas. The names can be anything you wish, as long as they are valid variable names (ie, starts with letters or underscore, and contains only letters, numbers, or underscore.)

You can have as many parameters as you like, anything from zero to whatever.

Later on, I'll show you how to define default values for the parameters, as well as how to slurp up extra parameters. For now, just know that these things exist.

Doc String

Doc strings are optional. Although you don't need to specify one for every function you write, I strongly encourage you to do so.

The description should include at least the following elements to be useful:

  • What the parameters mean.
  • What the return value is.

The doc string is simply a string that is in the first line of the function. Any string, raw, unicode, triple-quoted, or otherwise, will do. However, in practice, people tend to use triple double quotes ("""..."""). I recommend you not buck this trend.

The doc string can be accessed by the function's __doc__ attribute.

print my_function.__doc__


Function Body

The body is a block of code. Remember the section on code flow? That colon at the end of the first line is the universal indicator that a code block follows. Everything that shares the same indent as the next line are part of that block, up until you go back to the original indent.

The function body can contain literally anything---even more function definitions!

Return Statement

The function body may also contain a return statement. The return statement looks like this:

return expression

Remember, expression can be any expression, from a single literal to a math expression or even a variable name, or some combination of the above.

The return statement can even include multiple expressions, interpreted as a tuple of those elements:

return expr1, expr2, expr3

Meaning

What does the above mean?

Well, as I mentioned earlier, it is an instruction to Python to create a new function with the function name, and assign it to the variable of the same name.

This function can be called, which we'll talk about later. The calling code must specify the proper number of parameters. These are values to match each parameter.

When the function is called, the incoming values are assigned to variables with the same name as the parameters. Then the code is executed as if those variables were just declared.

When the function completes, then the entire namespace that was inside the function is wiped away. The parameter variables, and any other variables you happened to create, are destroyed.

What does the "return" statement do? Kind of like "break" or "continue", it stops execution of the function immediately. That means no more code beyond the return statement will be run. Then it evaluates the expression that is part of the statement. Finally, it "returns" the value as the result of calling the function. In the case of multiple expressions in the return statement, the expressions are interpreted as a tuple and the tuple is returned.

If you don't have a return statement, that's OK. When the function runs out of lines of code in its body, it will simply pretend like you wrote "return None" at the end, and return the value "None" as the result.

Parameters and Arguments

Two more words you'll need to know. I'll try to be very specific when using them throughout the tutorial.

Parameter
The parameters of a function are the names we assign to incoming values when the function is called.
Argument
The arguments of a function call are the values that are passed in to the function when it is called.

In other words, when you call a function, you need to specify the arguments. These get translated into the parameters of the function. If the arguments and parameters do not match, then the function can't be called and a TypeError is thrown.

Interface

The interface of something describes what it looks like from the outside. Two things with the same interface can be substituted and the user of the thing won't be able to tell.

In the case of functions, the interface is:

  • The name of the function
  • The acceptable parameters of the function, including their name. (We'll talk about keyword arguments later.)
  • The return value of the function.

What happens inside a function is completely opaque to the calling code.

Think of the interface as the way something appears on the outside. Two things that appear identical have identical interfaces.

Two things may have different interfaces, but the differences may be irrelevant to your calling code. For instance, if you don't expect a return value, and the function returns something, it's not important.

This will go along with 'duck typing', which I'll describe later. If it looks like a duck, quacks like a duck, and swims like a duck, then it's a duck.

Examples

No Parameters

This is a simple function:

def nothing(): return None

When you call it, it doesn't take any parameters and it does nothing. It will return the value of "None".

There's an even simpler way to write that function:

def nothing(): pass

"pass", if you recall, does nothing, but it passes as a statement which fills the requirement for a body.

One Parameter

This is a function that has a single parameter. It doubles it and returns the doubled value.

def double(x):
    """Returns twice x"""
    return 2*x

Here's another function. It takes a parameter, but it returns nothing. That's because the author probably forgot a return statement!

def double(x):
    """Should return twice x, but actually returns None"""
    2*x

The above is valid code, it's just silly.

Here's one that detects whether a number is even or odd.

def even_odd(number):
    """Returns 'even' or 'odd' depending on whether the number is even or odd."""
    if number%2 == 0: return "even"
    else: return "odd"

And here's one that determines, by a rather inefficient way, whether a number is prime.

def is_prime(z):
    """Returns True or False depending on whether z is prime, using a simple but inefficient algorithm."""
    for i in range(2, z):
        if z%i == 0:
            # It's divisible by i, so it's not prime
            return False

    # It wasn't divisible by anything, so it's prime
    return True

This will calculate the first n items in the Fibonacci sequence.

def fib(n):
    """Calculates the nth term in the Fibonacci sequence."""
    a,b = 0,1
    for i in range(n):
        a,b=b,a+b
    return a

Multiple Parameters

This function calculates the product of several numbers:

def product(i, j, k, l):
    """Returns the product of i, j, k and l."""
    return i*j*k*l

This function calculates the quadratic equation ax2 + bx + c:

def quadratic(a, b, c, x):
    """Calculates ax^2 + bx + c"""
    return a*x*x + b*x + c

This one solves the quadratic equation ax2 + bx + c = 0 for x. Since there are two possible answers, it returns both.

import math
def solve_quadratic(a, b, c):
    """Solves ax^2 + bx + c = 0 for x, returning the two possible values of x. Doesn't handle imaginary numbers well."""
    discriminant = math.sqrt(b*b-4*a*c)
    return (-b+discriminant)/(2*a), (-b-discriminant)/(2*a)

In Practice

  • Functions represent a unit of intelligence in your program. You can stick all sorts of things into a function, and it will remember for you how it is supposed to figure out what it needs to figure out.
  • Functions require a name, a list of parameters, and the function body.
  • Choose a good name for a function that is descriptive, but not terribly long.
  • Choose a good doc string for a function that describes what the inputs are and what the output is.
  • Choose good descriptive names for the parameters to the function. You'll be stuck using them in the function body.
  • Don't forget your return statement! If you do forget, Python will return None for you.

Homework

When writing functions, be sure to name them with an appropriately short yet descriptive name, and provide a descriptive doc string that specifies what the incoming parameters mean and what the function does.

  1. Write a function that accepts no parameter and always returns 5. Name this function something descriptive, and be sure to specify a doc string.
  2. Write a function that accepts two parameters, and returns True if the first is greater than the other, or False otherwise.
  3. Write a function that accepts 5 parameters, and adds them together.
  4. Write a function that returns None if none of the 4 parameters you give it are greater than 5. If any are greater than 5, it returns the one that is.
  5. Write a function of one parameter that returns:
    • The number
    • Twice the number
    • The number squared
    • The number divided by 2