HOLIDAY SALE! Save 50% on Membership with code HOLIDAY50. Save 15% on Mentorship with code HOLIDAY15.

7) Decorators Lesson

Python Decorators Step 1: View Python Functions as Objects

6 min to complete · By Martin Breuss

Decorators are functions that return functions. It might help to take a step back to better understand what that means. Start your journey into decorators by defining a normal Python function:

def say_hi():
    print("Hi.")

You can now call say_hi() and spread a lot of happy greetings throughout the world:

say_hi()  # OUTPUT: Hi.

Everything is an Object

Functions are super useful, and you already know that. But from Python's perspective, they're nothing special. They are what everything is. Remember the fundamental truth at the base of this course module:

In Python, everything is an object.

A function is just another object, meaning you can treat it like you'd treat any other object.

Python Functions Are Just Objects

To better understand what that means, you'll now do something to a function object that you usually don't do. You'll assign it to a variable and then call that variable instead of calling the initially assigned name for it:

hi = say_hi
hi()  # OUTPUT: Hi.

Usually, you'll directly call the variable reference you assigned when defining the function. But nothing prevents you from creating another reference to that function object and calling the second reference instead. This is what you did in the code snippet above.

Colorful illustration of a light bulb

Info: Using the parentheses (()) after a callable object in Python is what executes the code. You can call any reference that points to a callable object.

Functions in Lists

Okay, looks like you're heating up here! What else can you do with a function, you're asking? For example, you can define a second function object and then put both of them into a list:

def say_moo():
    print("moooooooo!")

function_list = [say_hi, say_moo]

Your function_list object now contains two function objects; one is called say_hi, and the other one is called say_moo. You placed them in a list just like you would do with any other Python object, such as an integer or a string.

When you start handling functions in this way, you might notice that they aren't all that special. And just like any other object in a list, you can access the function objects via indexing:

print(function_list[0]) 
# OUTPUT: <function say_hi at 0x10659d1e0>;

say_hi is just a normal Python object that hangs out at a specific list index. Keep in mind that you added the function objects without adding the brackets (()). You didn't want to call the function, but instead, you just parked them in your list.

But can you also call the function while it's still sitting inside the list? Yes, you can:

print(function_list[0]())  
# OUTPUT: Hi.

In this example, you're grabbing the first function object inside your function_list, and you call that object using the parentheses syntax. This will execute the function body and print your greeting to the console.

Callable Objects

As you can see, functions are just objects in Python. Specifically, they are callable objects. This means that they are fundamentally the same as any other Python object and have the additional feature of being able to call them. Like many language features, their callability is implemented using a dunder method, aptly named __call__().

Illustration of a lighthouse

Tasks

  • What happens when you call the functions inside the list while assigning the function_list variable? function_list = [say_hi(), say_moo()]
  • What will the output be if you print(function_list) after that assignment?
  • Use breakpoint() to check it out for yourself!
  • Challenge yourself and build a custom class where you implement the __call__() method. What can you do with your objects now?

With the normality of functions in mind, you'll next revisit the concept of scopes in Python, which is another building block that can help you better understand decorators.

Colorful illustration of a light bulb

Additional Resources

  • Official Python Docs: Calls

Summary: Step 1: View Python Function as Objects

  • Everything in Python is an object
  • Functions are Python objects
  • Functions are normally defined with def and called with ()
  • Functions can be assigned to variables and collections