What are Python Decorators? How do I use them?

A Guide to Modifying Function Behavior

What are Python Decorators? How do I use them?

What are Python Decorators?

Decorators are a tool used in Python(and many other languages) that can be used to modify the behavior of a function or class. Decorators are essentially functions that accept another function as an argument and then return a function that would modify the input function in some way.

Decorators can be used for a variety of purposes, such as logging, authentication, process time auditing etc. They are a powerful tool for developers use to create more concise, flexible code.

Using Python Decorators:

Here is a basic example of a decorator in Python:

def my_decorator(func):    
    def wrapper():        
        print("Before the function is called.")        
        func()        
        print("After the function is called.")    
        return wrapper


@my_decorator
def say_hello():    
    print("Hello!")

say_hello()

In this example, the my_decorator function is defined to take another function func as an argument. It returns a new function wrapper that adds behavior before and after the input function is called.

The @my_decorator syntax above the say_hello function is called a decorator syntax. It applies the my_decorator to the say_hello function. The say_hello function is now modified to include the behavior defined in the decorator.

When the say_hello function is called, the output will be:

Before the function is called.
Hello!
After the function is called.

This is just a simple example demonstrating how this works, but isn't something you would really use in your code. Let's look at a few examples that would be a bit more applicable to something you may see in the real world.

Timing Decorator Example:

import time


def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print("Elapsed time: {}".format(end_time - start_time))
        return result
    return wrapper


@timer
def my_func():
    time.sleep(2)


my_func() #Output: Elapsed time: 2.0000710487365723

This decorator would measure the time in which the method my_func took to execute. It uses the time module to calculate the elapsed time and displays it. This would be useful in the event you want to analyze your functions for time effeciency.

Authentication Decorator Example:

def requires_auth(func):
    def wrapper(*args, **kwargs):
        if not authenticated:
            raise Exception("Authentication required!")
        return func(*args, **kwargs)
    return wrapper


@requires_auth
def my_secret_function():
    print("This function is secret!")


authenticated = False
my_secret_function() # Output: Exception: Authentication required
authenticated = True
my_secret_function() # Output: This function is secret!

This decorator restricts access to a function unless the user is authenticated. It raises an exception if the user is not authenticated and returns the function's result if they are.

Decorators are a powerful tool that can be used to enhance the behavior or flexibility of Python projects. This is a basic overview of the paradigms of how they work and how they can be implemented. If you're interested in knowing more about them I recommend you check out a deeper dive!

Thanks for visiting!