🔄 The Relationship (Context and Decorator)

Both context managers and decorators are about wrapping behavior


🧩 Conceptual Connection

Feature Context Manager Decorator
Wraps a block of code Yes (with statement) No (wraps a function)
Wraps a function Not directly (but can simulate) Yes (@decorator)
Uses @contextmanager? Yes, for function-style Not required (but can use it)
Can use yield for flow? Yes Only if using generator-based decorators

⚡ Example Side-by-Side

🎩 A Context Manager That Times a Block

from contextlib import contextmanager
import time

@contextmanager
def timer():
    start = time.time()
    yield
    end = time.time()
    print(f"Elapsed: {end - start:.2f} seconds")

with timer():
    time.sleep(1)

🪄 A Decorator That Times a Function

import time

def timeit(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"Elapsed: {end - start:.2f} seconds")
        return result
    return wrapper

@timeit
def slow_function():
    time.sleep(1)

slow_function()

🔁 Combining Both: Context Manager Inside a Decorator

from contextlib import contextmanager
import time

@contextmanager
def timer():
    start = time.time()
    yield
    end = time.time()
    print(f"[Context] Took {end - start:.2f}s")

def use_timer(func):
    def wrapper(*args, **kwargs):
        with timer():
            return func(*args, **kwargs)
    return wrapper

@use_timer
def do_work():
    time.sleep(1)

do_work()

🧠 Summary

Similarity Description
Both are wrappers Context managers wrap code blocks, decorators wrap functions
Pre/post logic Both allow setup/teardown logic
Cleaner code They reduce boilerplate and improve readability

🎯 Think of it like this:


Thanks for Stopping by! Happy Leet coding

Connect with me on

Github LinkedIn Gmail Youtube