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
Decorators (In Depth) | Thuta Learning