Fundamentals 7 min read

10 Practical Python Decorator Patterns to Supercharge Your Code

This article introduces ten useful Python decorator patterns—such as timing, logging, authentication, caching, input validation, retry, permission checks, type checking, singleton, and call counting—explaining their purpose, providing clear code examples, and showing how to apply them to enhance functions and classes.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
10 Practical Python Decorator Patterns to Supercharge Your Code

Decorators are a powerful Python feature that let you modify, extend, or wrap functions and classes without changing their source code. A decorator is essentially a higher‑order function that receives a function (or class) as an argument and returns a new callable.

1. Timer Decorator (measure execution time)

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@timer
def my_function():
    # function implementation
    pass

my_function()

2. Logger Decorator (record call details)

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

@logger
def my_function():
    # function implementation
    pass

my_function()

3. Authentication Decorator (protect functions)

def authenticate(func):
    def wrapper(*args, **kwargs):
        if is_authenticated():
            return func(*args, **kwargs)
        else:
            raise Exception("Unauthorized access")
    return wrapper

@authenticate
def protected_function():
    # function implementation
    pass

protected_function()

4. Cache Decorator (memoize results)

def cache(func):
    cached_results = {}
    def wrapper(*args):
        if args in cached_results:
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        return result
    return wrapper

@cache
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

fibonacci(10)

5. Input‑Validation Decorator (type checking)

def validate_input(func):
    def wrapper(*args, **kwargs):
        for arg in args:
            if not isinstance(arg, int):
                raise ValueError("Arguments must be integers")
        return func(*args, **kwargs)
    return wrapper

@validate_input
def multiply(a, b):
    return a * b

multiply(2, 3)

6. Retry Decorator (automatic retries on failure)

import time

def retry(func):
    def wrapper(*args, **kwargs):
        max_retries = 3
        for _ in range(max_retries):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                print(f"Function {func.__name__} failed: {e}")
                time.sleep(1)
        raise Exception(f"Function {func.__name__} failed after max retries")
    return wrapper

@retry
def connect_to_server():
    # function implementation
    pass

connect_to_server()

7. Permission‑Check Decorator (role‑based access)

def check_permission(permission):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if has_permission(permission):
                return func(*args, **kwargs)
            else:
                raise Exception("Permission denied")
        return wrapper
    return decorator

@check_permission("admin")
def delete_user(user_id):
    # function implementation
    pass

delete_user(123)

8. Type‑Check Decorator (input and output validation)

from functools import wraps
from typing import List

def type_check(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        for arg in args:
            if not isinstance(arg, int):
                raise TypeError("Arguments must be integers")
        result = func(*args, **kwargs)
        if not isinstance(result, List):
            raise TypeError("Return value must be a list")
        return result
    return wrapper

@type_check
def process_data(data):
    # function implementation
    pass

process_data([1, 2, 3])

9. Singleton Decorator (ensure a single instance)

def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class DatabaseConnection:
    # class implementation
    pass

db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True

10. Counter Decorator (track call count)

def counter(func):
    count = 0
    def wrapper(*args, **kwargs):
        nonlocal count
        count += 1
        print(f"Function {func.__name__} called {count} times")
        return func(*args, **kwargs)
    return wrapper

@counter
def my_function():
    # function implementation
    pass

my_function()
my_function()

These ten decorator examples illustrate how to enhance functions and classes in Python, providing reusable patterns for timing, logging, security, caching, validation, resilience, permission control, type safety, singleton behavior, and usage statistics. Adapt and combine them as needed for your specific projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

programmingSoftware Engineeringbest practicesCode Examplesdecorators
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.