Python Decorators Explained For Beginners

In the world of Python programming, decorators can be an elegant and powerful tool in the hands of experienced developers.

Decorators give you the ability to modify the behavior of functions without altering their source code, providing a concise and flexible way to enhance and extend their functionality.

In this article, I'll go over the intricacies of how to use decorators in Python, and show examples of where they are useful.

Quick Function Recap

Simply put, a function is a way of running a block of code repeatedly with different arguments.

In other words, it can take inputs, use those inputs to run some pre-defined set of code, and then return an output.

functions

Functions take in inputs, use it to run a set of code and returns an output

In Python, a function is written like so:

def add_one(num):
	return num + 1

When we want to call it, we can write the function's names with parenthesis and pass in the necessary inputs (arguments):

final_value = add_one(1)
print(final_value) # 2

Note that for the most part, arguments and parameters mean the same thing. They are the variables used in the function.

The difference lies in where we are referring to them. Arguments are what we pass into the function when calling it, and parameters are what is declared in the function.

How to Pass Functions as Arguments

Commonly, when calling functions with arguments, we pass values such as Integers, Floats, Strings, Lists, Dictionaries and other data types.

But, something we can also do is to pass a function as an argument as well:

def inner_function():
	print("inner_function is called")
    
def outer_function(func):
	print("outer_function is called")
 	func()
   
outer_function(inner_function)
# outer_function is called
# inner_function is called
    

In this example we create two functions: inner_function and outer_function.

outer_function has a parameter called func which it calls after it itself is called.

first_class_citizens

outer_function executes first. It then calls the function that was passed as a parameter

Think about it like how we can treat functions like any other value or variable.

The proper term for this is that functions are first class citizens. This means that they are just like any other object and can be passed as arguments into other functions, be assigned to variables, or returned by other functions.

So, outer_function can take in a function as a parameter and call it when it is executed.

How to Return Functions

Another benefit of being able to treat functions as objects is that we can define them in other functions and return them as well:

def outer_function():
	print("outer_function is called")
    
	def inner_function():
    		print("inner_function is called")
      
	return inner_function

Note that in this example, when we return inner_function, we didn't call it.

We only returned the reference to it, so that we can store and call it later on:

returned_function = outer_function()
# outer_funciton is called

returned_function()
# inner_function is called

If you are like I am, this might seem interesting and all, but you are still probably wondering how this can be useful in actual programs 🤔.  This is something we'll take a look at in a moment!

How to Create Decorators in Python

Accepting functions as arguments, defining functions within other functions, and returning them are exactly what we need to know to create decorators in Python. We use decorators to add additional functionality to existing functions.

For example, if we wanted to create a decorator that will add 1 to the return value of any function, we can do it like so:

def add_one_decorator(func):
	def add_one():
    	value = func()
        return value + 1
        
	return add_one

Now, if we have a function that returns a number, we can use this decorator to add 1 to whatever value it outputs.

def example_function():
	return 1
    
final_value = add_one_decorator(example_function)
print(final_value()) # 2

In this example, we call the add_one_decorator function and pass in the reference to example_function.

When we call the add_one_decorator function, it creates a new function, add_one, defined within it and returns a reference to this new function. We store this function in the variable final_value.

So, when executing the final_value function, the add_one function is called.

The add_one function defined within add_one_decorator will then call example_function, store its value, and add one to it.

Ultimately, this results in 2 being returned and printed to the console.

python_decorators-1

Process of how the code will execute

Notice how we didn't have to change the original example_function to modify its return value and to add functionality to it. This is what makes decorators so useful!

Just to clarify, decorators aren't specific to Python. They're a concept that can be applied in other programming languages. But in Python, you can make use of them easily using the @ syntax.

How to Use the @ Syntax in Python

Back to Top