Lesson 4: Functions

Functions are reusable pieces of programs. They allow you to give a name to a block of statements, allowing you to run that block using the specified name anywhere in your program and any number of times. This is known as calling the function. We have already used a few built-in functions such as type, int, float, and format.

Python provides a number of important built-in functions that we can use without needing to provide the function definition. The creators of Python wrote a set of functions to solve common problems and included them in Python for us to use. Here are a few examples:

The min and max Functions

The max and min functions give us the largest and smallest values in a list, respectively:

Code Output
max('Hello world') w
max([10,9,3,5,7,2]) 10
min('Hello world')  (space)
min([10,9,3,5,7,2]) 2

The max function tells us the “largest character” in the string (which turns out to be the letter “w”) and the min function shows us the smallest character (which turns out to be a space).

The len Function

Another very common built-in function is the len function which tells us how many items are in its argument. If the argument to len is a string, it returns the number of characters in the string. If the argument is a sequence, then it counts the number of objects in the sequence.

Code Output
len('Hello world') 11
len([10,9,3,5,7,2]) 6

The function concept is probably the most important building block of any non-trivial software (in any programming language), so we will explore various aspects of functions in this chapter.

Defining Functions

In Python, functions are defined using the def keyword. After this keyword comes an identifier name for the function, followed by a pair of parentheses which may enclose some names of variables, and by the final colon that ends the line.  Next follows the block of statements that are part of this function.

Just like with conditional statements and iterations, the first line of the function definition is called the header; the rest is called the body. The header has to end with a colon and the body has to be indented. By convention, the indentation is always four spaces. The body can contain any number of statements.

def [function_name]():
    [statements]

After we define the function, we can call it by name – and even pass information into it.

An example will show that this is actually very simple:

Example: Say Hello Function

def say_hello():
    # block belonging to the function
    print('hello world')
    # End of function
    
say_hello()  # call the function
say_hello()  # call the function again

Output:

hello world
hello world

How It Works

We define a function called say_hello using the syntax as explained above. This function takes no parameters and hence there are no variables declared in the parentheses. Parameters to functions are just input to the function so that we can pass in different values to it and get back corresponding results.

Notice that we can call the same function twice which means we do not have to write the same code again.

Launch Exercise

Here is another example:

Code Output
# Here we define the function
def print_lyrics():
    print("I'm a lumberjack,")
    print("and I'm okay.")

# Here we call the function
print_lyrics()
I'm a lumberjack,
and I'm okay.

Once you have defined a function, you can use it inside another function. For example, to repeat the previous refrain, we could write an additional function called repeat_lyrics:

Code Output
# Here we define the second function
def repeat_lyrics():
    print_lyrics()
    print_lyrics()

# Here we call the second function
repeat_lyrics()
I'm a lumberjack,
and I'm okay.
I'm a lumberjack,
and I'm okay.

Pulling together the code fragments from the previous section, the whole program looks like this:

Code Output
# Here we define the first function
def print_lyrics():
    print("I'm a lumberjack,")
    print("and I'm okay.")

# Here we define the second function
def repeat_lyrics():
    print_lyrics()
    print_lyrics()

# Here we call the second function
repeat_lyrics ()
I'm a lumberjack,
and I'm okay.
I'm a lumberjack,
and I'm okay.

Our program contains two function definitions: print_lyrics and repeat_lyrics. Function definitions get executed just like other statements, but the effect is to create function objects. The statements inside the function do not get executed until the function is called, and the function definition generates no output.

As you might expect, you have to create a function before you can execute it. In other words, the function definition has to be executed before the first time it is called.

Launch Exercise

Launch Exercise

Flow of Execution

In order to ensure that a function is defined before its first use, you have to know the order in which statements are executed, which is called the flow of execution.

Execution always begins at the first statement of the program. Statements are executed one at a time, in order from top to bottom.

Function definitions do not alter the flow of execution of the program, but remember that statements inside the function are not executed until the function is called.

A function call is like a detour in the flow of execution. Instead of going to the next statement, the flow jumps to the body of the function, executes all the statements there, and then comes back to pick up where it left off.

That sounds simple enough, until you remember that one function can call another. While in the middle of one function, the program might have to execute the statements in another function. But while executing that new function, the program might have to execute yet another function!

Fortunately, Python is good at keeping track of where it is, so each time a function completes, the program picks up where it left off in the function that called it. When it gets to the end of the program, it terminates.

What’s the moral of this sordid tale? When you read a program, you don’t always want to read from top to bottom. Sometimes it makes more sense if you follow the flow of execution.