Thuta Learning
AdvancedProgrammingbeginner

Decorators (In Depth)

Relax. We'll talk through this in plain words โ€” no textbook voice.

๐ŸŽ€ Lesson 63: Python Decorators (Functions Enhancing Functions)

1. What Is a Decorator?

In short โ†’ A decorator is a kind of higher-order function that takes a function as input, adds extra features to it, and returns the enhanced version.

In detail โ†’ A decorator is a higher-order function that takes another function as input, adds extra functionality, and returns a new function.

2. Why Use Decorators?

  • You can add extra features to a function without changing it
  • They help you reuse code
  • Commonly used for logging, authentication, and performance measurement

3. Summary

โœ… Decorator = a higher-order function that enhances a function

โœ… Syntax โ†’ @decorator_name

โœ… Use cases โ†’ logging, authentication, performance, caching

โœ… Built-in decorators โ†’ @staticmethod, @classmethod, @property

python
# ===== 1. Basic Decorator =====
def my_decorator(func):
    def wrapper():
        print("Before function runs")
        func()
        print("After function runs")
    return wrapper

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

print("===== Basic Decorator =====")
say_hello()

# ===== 2. Decorator with Arguments =====
print(f"\n===== Decorator with Arguments =====")

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Function is running...")
        return func(*args, **kwargs)
    return wrapper

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

print(f"add(5, 3) = {add(5, 3)}")

# ===== 3. Logging Decorator =====
print(f"\n===== Logging Decorator =====")

def log(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        result = func(*args, **kwargs)
        print(f"{func.__name__} finished")
        return result
    return wrapper

@log
def greet(name):
    print(f"Hello, {name}")

greet("Sai")

# ===== 4. Timing Decorator =====
print(f"\n===== Timing Decorator =====")

import time

def timing(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f} seconds")
        return result
    return wrapper

@timing
def slow_function():
    time.sleep(0.1)
    return "Done"

slow_function()

# ===== 5. Built-in Decorators =====
print(f"\n===== Built-in Decorators =====")
print("@staticmethod โ†’ Static method in class")
print("@classmethod โ†’ Class method")
print("@property โ†’ Getter method as property")
You should see
===== Basic Decorator ===== Before function runs Hello! After function runs ===== Decorator with Arguments ===== Function is running... add(5, 3) = 8 ===== Logging Decorator ===== Calling greet Hello, Sai greet finished ===== Timing Decorator ===== slow_function took 0.1002 seconds Done ===== Built-in Decorators ===== @staticmethod โ†’ Static method in class @classmethod โ†’ Class method @property โ†’ Getter method as property