Useful Data Tips

Python Decorators Explained Simply

⏱️ 30 sec read 🐍 Python

Decorators are functions that modify the behavior of other functions. They use the @decorator syntax to add functionality without changing the original function's code.

Basic Decorator

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

@timer
def slow_function():
    import time
    time.sleep(2)
    return "Done"

slow_function()  # Prints: slow_function took 2.00 seconds

Logging Decorator

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

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

add(3, 5)
# Output:
# Calling add with args=(3, 5), kwargs={}
# add returned 8

Multiple Decorators

def uppercase(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def exclaim(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"
    return wrapper

@exclaim
@uppercase
def greet(name):
    return f"hello {name}"

print(greet("alice"))  # Output: HELLO ALICE!

Decorator with Arguments

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

@repeat(times=3)
def say_hello():
    print("Hello!")

say_hello()
# Output:
# Hello!
# Hello!
# Hello!

Practical Use Cases

Pro Tip: Use functools.wraps to preserve the original function's metadata. This keeps __name__ and __doc__ intact when using decorators.

← Back to Python Tips