Python Tutorial (23) - Decorators

Time: Column:Python views:195

Python Decorators

Decorators in Python are an advanced feature that allows you to dynamically modify the behavior of functions or classes.

A decorator is essentially a function that takes another function as its argument and returns a new function or modifies the original one.

The syntax for using decorators involves the @decorator_name placed before the function or method you want to decorate.

Python also provides built-in decorators such as @staticmethod and @classmethod, which are used to define static methods and class methods, respectively.


Use Cases of Decorators:

  • Logging: Decorators can be used to log information about function calls, arguments, and return values.

  • Performance Analysis: They can measure the execution time of a function.

  • Access Control: Decorators can restrict access to certain functions.

  • Caching: They can implement caching of function results to improve performance.


Basic Syntax

In Python, decorators allow you to dynamically add or modify functionality to functions without altering their code. Essentially, a decorator is a function that takes another function as input and returns a modified version of it.

Syntax Example

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # Code before calling the original function
        before_call_code()
        
        result = original_function(*args, **kwargs)
        
        # Code after calling the original function
        after_call_code()
        
        return result
    return wrapper

Using a Decorator

@decorator_function
def target_function(arg1, arg2):
    pass  # Original function implementation

Explanation:

  • decorator_function is a decorator that takes original_function as an argument.

  • wrapper is an inner function that is called instead of the original function, allowing you to add extra behavior before and after the original function call.

  • When you apply @decorator_function to target_function, Python automatically passes target_function to decorator_function and replaces the original function with the wrapper.

Using a Decorator

Decorators are applied by placing the @ symbol before the function definition, like this:

@time_logger
def target_function():
    pass

This is equivalent to:

def target_function():
    pass

target_function = time_logger(target_function)

This passes the target_function to the time_logger decorator, which returns a new function, assigning it back to target_function. Thus, whenever target_function is called, the decorated version of the function is executed.

Decorators allow developers to extend the functionality of their programs efficiently while maintaining clean code.


Parameterized Decorators

Decorators can also accept arguments, allowing for even greater flexibility.

Example

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

In this code, the repeat function is a parameterized decorator that takes an integer n. It returns a decorator that repeats the execution of the original function n times. When greet is decorated with @repeat(3), it prints the greeting three times.


Class Decorators

In addition to function decorators, Python also supports class decorators. A class decorator is a class that implements the __call__ method. It takes a function as its argument and returns a modified version of that function.

Example

class DecoratorClass:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        # Code before the original function is called
        result = self.func(*args, **kwargs)
        # Code after the original function is called
        return result

@DecoratorClass
def my_function():
    pass

In this example, DecoratorClass acts as a decorator. When @DecoratorClass is applied to my_function, the __call__ method of DecoratorClass is invoked each time my_function is called.