Decorator in Python

June 20, 2024
16 views
Decorator in Python

One interesting and powerful feature in Python is the decorator. Decorators allow you to modify the behavior of functions or classes in a very flexible and reusable way, without changing their actual code. This makes them extremely useful for logging, enforcing access control, instrumentation, caching, and more.

Example: Using a Decorator for Logging

Let's say we want to log when a function is called. Instead of adding logging code inside every function, we can use a decorator.

Step 1: Define the Decorator

A decorator is simply a function that takes another function and extends its behavior.

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__} with arguments {args} and {kwargs}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned {result}")
        return result
    return wrapper

Step 2: Use the Decorator

You can apply the decorator to any function using the `@decorator_name` syntax.

@log_decorator
def add(a, b):
    return a + b

@log_decorator
def multiply(a, b):
    return a * b

# Test the decorated functions
result_add = add(2, 3)
result_multiply = multiply(4, 5)

What Happens Here?

1. Defining the Decorator:

  • `log_decorator` is defined to take a function `func` as an argument.
  • Inside `log_decorator`, a new function `wrapper` is defined, which wraps around the original function `func`.
  • The `wrapper` function logs the function name and arguments before calling `func`, and logs the result after calling `func`.

2. Applying the Decorator:

  •   The `@log_decorator` syntax applies the decorator to the functions `add` and `multiply`.
  •   When `add(2, 3)` or `multiply(4, 5)` is called, it actually calls the `wrapper` function defined inside the decorator.

Output:

Calling function add with arguments (2, 3) and {}
Function add returned 5
Calling function multiply with arguments (4, 5) and {}
Function multiply returned 20

Why is This Interesting?

Decorators are a prime example of Python’s flexibility and the power of higher-order functions. They allow for the separation of concerns, letting you add or modify functionality in a clean, reusable way without altering the core logic of the functions they decorate. This can lead to cleaner, more maintainable, and more readable code.

Advanced Use Cases

  • Caching: Implementing memoization to cache expensive function calls.
  • Access Control: Checking user permissions before allowing access to certain functions.
  • Instrumentation: Automatically timing function execution or counting how often a function is called.

Example: Caching with a Decorator

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# Test the caching decorator
print(fibonacci(100))  # Computes the 100th Fibonacci number efficiently

Here, the `lru_cache` decorator from the `functools` module caches the results of the `fibonacci` function, making subsequent calls with the same arguments return much faster.

Decorators highlight Python’s expressive syntax and its emphasis on readability and simplicity, making them a fascinating and useful feature of the language.

Python

Share this article

Ready to Transform Your Business?

Let's discuss how we can help you implement these solutions in your organization. Contact us for a free consultation.

Leo Pathu - CEO Quilltez

Leo Pathu

CEO - Quilltez

Creating a tech product roadmap and building scalable apps for your organization.

Thank You!

Your message has been sent successfully. We'll get back to you soon!

Something went wrong. Please try again.

Start Your Project

Your information is secure and will never be shared.