Saturday, May 17, 2025

Decorators in Python

In Python, decorators are a powerful and elegant way to modify or enhance the behaviour of functions or methods without changing their code.

What is a decorator?

A decorator is a function that takes another function as input and returns a new function with added behaviour.

def my_decorator(func):
    def wrapper():
        print("Before the function runs")
        func()
        print("After the function runs")
    return wrapper

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

say_hello()
# This is a simple decorator that adds functionality before and after the
# function call.
# You can use decorators to modify the behaviour of functions or methods in Python.
# # Decorators are often used in web frameworks like Flask and Django
#  to add functionality to routes or views.
# # For example, in Flask, you can use decorators to define routes and
# Add middleware functionality.
# # # Here's an example of a Flask route using a decorator:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
   return 'Hello, World!'
# # In this example, the @app.route('/') decorator tells Flask to call the
# # hello_world function when the root URL is accessed.

Built-in Decorators Examples

1.Set a Static Method

class MyClass:
    @staticmethod
    def greet():
        print("Hello")


2. Set a Instance Method

class MyClass:
    name = "Python"
   
    @classmethod
    def show(cls):
        print(cls.name)

3. Set a Property.
class Circle:
    def __init__(self, radius):
        self._radius = radius
   
    @property
    def area(self):
        return 3.14 * self._radius ** 2

Decorator Example

class FakeDBConnection:
    def connect(self):
        print(" DB connected")
   
    def commit(self):
        print("Transaction committed")
   
    def rollback(self):
        print("Transaction rolled back")
   
    def close(self):
        print("DB connection closed")

db = FakeDBConnection()

# Decorator without @wraps
def db_transaction(func):
    def wrapper():
        db.connect()
        try:
            result = func()
            db.commit()
            return result
        except Exception as e:
            db.rollback()
            print(f"Error: {e}")
        finally:
            db.close()
    return wrapper

# Function using the decorator
@db_transaction
def insert_user():
    """Insert a new user into the database."""
    print("Inserting user into database")
    # raise Exception("Simulated insert error")

insert_user()


Chaining of Decorators in Python

Chaining decorators means applying multiple decorators to a single function,

one after the other.

def decorator_one(func):
    def wrapper():
        print("Decorator One: Before")
        func()
        print("Decorator One: After")
    return wrapper

def decorator_two(func):
    def wrapper():
        print("Decorator Two: Before")
        func()
        print("Decorator Two: After")
    return wrapper

@decorator_one
@decorator_two
def say_hello():
    print("👋 Hello")

say_hello()
# This example demonstrates how to use multiple decorators on a single function.
# The order of decorators matters; the innermost decorator is applied first.

Decorator pattern for lofging in text file.

import datetime

def log_to_file(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        with open("log.txt", "a") as f:
            f.write(f"{datetime.datetime.now()}: Called {func.__name__}\n")
        return result
    return wrapper

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

if __name__ == "__main__":
    say_hello()




No comments:

Post a Comment