top of page
Writer's pictureSteve Paynter

Decorators - Crib Sheet



In Python, a decorator is a special function that modifies or enhances the behavior of another function. Decorators are used to add extra functionality to functions or methods without changing their source code. In this article, we'll discuss how decorators work in Python and provide examples to illustrate their usage.


Basic Syntax


In Python, decorators are implemented as functions that take another function as an argument and return a new function that may modify the input function's behavior. Here's the basic syntax for defining and using a decorator in Python:


def decorator(func): 
    def wrapper(*args, **kwargs): 
    # Do something before the function is called 
    result = func(*args, **kwargs) 
    # Do something after the function is called 
    return result 
return wrapper 

@decorator 
def my_function(): 
    # Do something 
    pass

In this example, we define a decorator function decorator that takes another function func as an argument. The decorator function then defines a new function wrapper that modifies the behavior of the input function by adding extra functionality before and after it is called. Finally, the decorator function returns the modified function wrapper for use elsewhere.


To use the decorator, we simply apply it to the function we want to modify using the @decorator syntax. In this case, we're applying the decorator function to the my_function function.


Practical Examples


Now let's look at some practical examples of decorators in Python.


Timing a Function Call


Suppose we want to time how long it takes to run a particular function. We can create a decorator that prints the time taken to execute the function. Here's how we can do it:


import time 

def time_it(func): 
    def wrapper(*args, **kwargs): 
        start = time.time() 
        result = func(*args, **kwargs) 
        end = time.time() 
        print(f"{func.__name__} took {end - start:.2f} to run.")
        return result 
    return wrapper @time_it 

def my_function(): 
    time.sleep(1) 
    
my_function()  # Output: "my_function took 1.00 seconds to run."

In this example, we define a decorator function time_it that takes another function func as an argument. The decorator function then defines a new function wrapper that records the start and end times of the function call, calculates the time taken to execute it, and prints the result. Finally, the decorator function returns the modified function wrapper for use elsewhere.


To use the decorator, we apply it to the my_function function using the @time_it syntax. When we call my_function, the decorator prints the time taken to execute the function.


Logging Function Calls


Suppose we want to log all the calls to a particular function. We can create a decorator that prints a message every time the function is called. Here's how we can do it:

def log_calls(func): 
    def wrapper(*args, **kwargs): 
    print(f"Calling {func.__name__} with args={args} kwargs={kwargs}") 
    result = func(*args, **kwargs) 
    print(f"Finished calling {func.__name__}") 
    return result 
return wrapper 

@log_calls 
def my_function(x, y): 
    return x + y 
    
my_function(1, 2) # Output: "Callingmy_function with args=(1, 2) kwargs={}" # "Finished calling my_function"

In this example, we define a decorator function log_calls that takes another function func as an argument.


The decorator function then defines a new function wrapper that logs a message before and after the input function is called. Finally, the decorator function returns the modified function wrapper for use elsewhere.


To use the decorator, we apply it to the my_function function using the @log_calls syntax. When we call my_function, the decorator prints a message indicating that the function is being called, and another message indicating that it has finished running.


Conclusion


Decorators are a powerful and flexible feature of Python that allow us to modify the behavior of functions and methods without changing their source code. They're particularly useful for adding extra functionality to existing code, and for implementing cross-cutting concerns such as logging, authentication, and error handling.

In this article, we've covered the basic syntax of decorators in Python and provided examples to illustrate their usage. We hope that this article has helped you understand decorators better and inspired you to start using them in your own code. Happy coding!

64 views0 comments

Recent Posts

See All

Comments


bottom of page