Python functions as doors

Understanding Python Functions With The Function Room (The White Room Series #2)

You’ve probably already learned about defining functions in Python and how to add parameters and return statements. You may even have learned about more advanced features of Python functions. But can you picture exactly what they do and what’s really happening behind the scenes when you call a function?

In this blog, I’ll build on The White Room analogy, which I introduced in the first post in the White Room Series. I’ll discuss what Monty, the computer program, is doing when you call a function, with or without arguments, and when you return values.

At the end of this post, Python functions will be your best friends!

Quick Recap: The White Room

If you’ve read the first post in the White Room Series, you can skip to the next section if you wish. Otherwise, you can either read that post first or read the very executive summary below.

  • The computer program is called Monty.
  • The infrastructure in which Monty, the program, works is a White Room, empty, except…
  • A few shelves on one of the walls, and…
  • A small, red booklet with built-in functions, constants, and other things Monty can start using.
  • When you assign data to a variable name, Monty brings an empty box, puts a label with the variable name on the outside, and he puts the data inside the box. Monty places the box on one of the shelves.
  • When you import a module, Monty goes out of the White Room and to a big library and fetches a book whose name is the module name. He brings this book to the White Room and places it on a shelf.
  • When you type any name in your program, Monty will look all around the White Room to find this name, either in the red "built-in" booklet, or as a "module" book, or a "variable" box.

How about functions? How do Python functions fit into this picture?

The Function Room

A function is a mini-program. As such, you can picture a function as being a separate room. When you define a function within your main program, you’re creating a Function Room which is right next to the White Room, which hosts the main program:

def do_something():
    my_number = 5
    print(my_number)
    
do_something()
print(my_number)

Let’s break down these lines of code:

  • You define the function do_something(). This is equivalent to building a new room adjacent to the main White Room. There’s a door connecting the White Room to the Function Room, and the label on the door says do_something.
  • When you type the name do_something in your code, Monty will look around the White Room to find this name. Although he won’t find this as a book or box on the shelves, he’ll find a reference to this name on the door leading to the Function Room. Therefore, Monty knows that this name refers to a function.
  • If the name do_something is not followed by parentheses, (), then Monty will simply note that you’re referring to that function. However, if you write do_something(), with the parentheses, Monty knows you’re asking him to go through the door and enter the Function Room.

Monty has now gone into the Function Room

  • He brings an empty box, labels it my_number and places the integer 5 in this box. Monty then places this box on the shelves in the Function Room.
  • The next line in the function definition refers to the names print and my_number. Monty will find print in the red, built-in booklet, which is present in every room, including Function Rooms. He’ll find the name my_number written on the box on the shelf, the box he just placed there a moment earlier.
  • Monty fetches the contents of the box my_number and uses it in print().
  • As all his work in the Function Room is done, Monty leaves the room and returns to the White Room, shutting the door to the Function Room behind him.

Monty is now back in the White Room

  • He has one more line to read, which is the final line of the code. There are no issues with the name print. However, Monty looks everywhere for the name my_number, and he can’t find it anywhere in the White Room. There was a box with that label he created earlier, but that’s in the Function Room. Monty is no longer in the Function Room, so the box is not available.
  • Monty therefore complains:
Traceback (most recent call last):
  File "<path>/<filename>.py", line 6, in <module>
    print(my_number)
NameError: name 'my_number' is not defined

This NameError is Monty’s way of saying that he can’t find anything with that name in the White Room.

Python Functions With A return Statement

Let’s add a bit more to this Python function:

def do_something():
    my_number = 5
    return my_number
    
do_something()
print(my_number)

Monty reads the function call do_something() and goes to the Function Room, as before. He puts 5 in a box and labels this box my_number. Next, he reads the return keyword, which is followed by the name my_number. Monty picks up the box my_number, takes its contents out, and he takes the contents of this box with him as he leaves the Function Room to go back to the White Room.

He does not take the box labelled my_number with him from the Function Room back to the White Room, but only its contents, that is the number 5.

Monty has completed the line with the function call do_something() now. He still has his hands full with the number 5, which he brought with him from the Function Room. Since Monty needs his hands free to proceed with the rest of his work, he finds the rubbish bin and throws the number 5 into the bin.

His hands are now free, and he can move on to the final line. But he still can’t find any box labelled my_number, no matter how much he looks around the White Room. So, he complains again in the same way he did earlier:

Traceback (most recent call last):
  File "<path>/<filename>.py", line 6, in <module>
    print(my_number)
NameError: name 'my_number' is not defined

Third attempt:

def do_something():
    my_number = 5
    return my_number
    
my_number = do_something()
print(my_number)

The line which includes the function call now has an assignment, too. When Monty returns to the White Room from his trip to the Function Room, holding the integer 5 in his hands, he gets an empty box, labels it my_number and puts the number 5 in this box. Now, he’ll be able to find a reference to the name my_number in the White Room.

Indeed, there’s no reason why the box in the White Room needs to have the same label as the one in the Function Room. They’re different boxes in different rooms:

def do_something():
    my_number = 5
    return my_number
    
some_number = do_something()
print(some_number)

Monty labels the box in the White Room using a different name to the one he used in the Function Room.

Python Functions With Arguments

How about Python functions with parameters?

def do_something_else(first_number, second_number):
    result = first_number + second_number
    return result
    
print(do_something_else(4, 10))

The function you define now has two parameters:

  • first_number
  • second_number

The parameters are the names you use in the function definition to represent the data you’ll pass to the function when you call it.

A small table is placed inside the Function Room, right next to the door, when the Function Room is constructed. There are two empty boxes on this table. One is labelled first_number and the other second_number. The parameters are empty boxes ready to be filled when Monty comes in.

On the final line of code above, Monty reads the names print and do_something_else. He starts with do_something_else, and he finds this label on the door leading to the Function Room. As this is a function call, Monty knows he needs to open the door and go through it. However, before he does this, he gets the integers 4 and 10. These are the arguments you pass to the function when you call it. He takes these two numbers with him into the Function Room.

As soon as he steps into the Function Room, he finds the two empty boxes waiting for him by the door. He puts the first integer in the first box, which is labelled first_number. The second integer goes in the second box, second_number.

Monty places these boxes on the shelves in the Function Room and carries on with his tasks.

Once Monty completes his tasks in the Function Room and returns to the White Room, carrying the number 14 in his hands, he uses this number straight away in print().

Final Words

When you picture Monty moving from White Room to Function Room, you’ll understand Python functions well!

There’s one more post to come in The White Room Series where I’ll discuss how The White Room and The Function Room fit in the whole Python ecosystem, which I call Python City. You can also read the full description of the White Room analogy in the standalone chapter of The Python Coding Book: The White Room: Understanding Programming.

Further Reading


Subscribe to

The Python Coding Stack

Regular articles for the intermediate Python programmer or a beginner who wants to “read ahead”


3 thoughts on “Understanding Python Functions With The Function Room (The White Room Series #2)”

  1. I have a question about function parameters from chapter 3 of your book.

    In the function “find_names_of_length(length, name_list)” there is the comparison “if len(name) == length”

    I made the mistake of invoking the function as “find_names_of_length(‘3’, list_of_names)”,
    but there was no error message indicating that the int “len(name)” was being compared to the character ‘3’.

    In a strongly typed language I would expect the compiler to recognize the error in types, but failing that I would at least expect a run-time error when trying to compare an int to a char.

    Is this a problem with Python, or my admittedly very novice understanding of how to code in Python?

    1. I wouldn’t call it a “problem” with Python, it’s the nature of Python’s dynamic typing. From the perspective of static-typed languages I can see how this looks weird, even “wrong”, but it’s at the core of how Python works.
      You’re correct, “3” == 3 is not an error and will simply return False.

Leave a Reply