What are Decorators?

Decorators are functions that modify other functions or classes. They use the @ syntax and are a powerful way to add functionality without modifying the original code.

Basic Decorator

Create a simple decorator:

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

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

say_hello()
# Output:
# Before function
# Hello!
# After function

Decorator with Arguments

Handle functions with parameters:

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

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

print(add(3, 5))  # Calling add, Result: 8, 8

Built-in Decorators

Python provides several built-in decorators:

class MyClass:
    @staticmethod
    def static_method():
        return "Static method"
    
    @classmethod
    def class_method(cls):
        return f"Class: {cls}"
    
    @property
    def my_property(self):
        return "Property value"

Decorator with Parameters

Create decorators that accept arguments:

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

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")  # Prints 3 times

Common Use Cases

  • Timing: Measure function execution time
  • Logging: Log function calls
  • Caching: Store function results
  • Validation: Check function arguments
  • Authentication: Verify user permissions

Best Practices

  • Use functools.wraps: Preserve function metadata
  • Keep decorators simple: Don't add too much complexity
  • Document decorators: Explain what they do
  • Test decorators: Ensure they work correctly

Next Steps

Learn about generators and context managers.