Creating Parameterized Decorators in Python: Logging, Performance, Authentication, Caching, and File Logging
This article demonstrates how to create various parameterized decorators in Python—including logging, performance measurement, authentication, caching, and file logging—by providing clear explanations and complete code examples for each use case in practical applications.
Introduction In Python, writing decorators that accept parameters is an advanced technique that allows additional configuration such as log levels, cache sizes, or authentication rules. This guide presents five practical examples with full source code.
1. Parameterized Logging Decorator The log decorator receives a logging level and logs function entry and exit with the result.
import logging
def log(level):
def decorator(func):
def wrapper(*args, **kwargs):
logging.log(level, f"Calling function '{func.__name__}'")
result = func(*args, **kwargs)
logging.log(level, f"Function '{func.__name__}' returned {result}")
return result
return wrapper
return decorator
@log(logging.DEBUG)
def debug_function():
return "Debug message"
@log(logging.INFO)
def info_function():
return "Info message"
logging.basicConfig(level=logging.DEBUG)
debug_result = debug_function()
info_result = info_function()
print(debug_result) # 输出:Debug message
print(info_result) # 输出:Info messageIn this example, the decorator accepts a log level and returns a proper decorator function.
2. Parameterized Performance Statistics Decorator The performance_stats decorator records execution time and call count, with a configurable precision.
import time
def performance_stats(precision=4):
def decorator(func):
call_count = 0
total_time = 0.0
def wrapper(*args, **kwargs):
nonlocal call_count, total_time
start_time = time.time()
print(f"Calling function '{func.__name__}'")
result = func(*args, **kwargs)
end_time = time.time()
elapsed_time = round(end_time - start_time, precision)
total_time += elapsed_time
call_count += 1
print(f"Function '{func.__name__}' returned {result} in {elapsed_time:.{precision}f} seconds")
print(f"Total calls: {call_count}, Total time: {total_time:.{precision}f} seconds")
return result
return wrapper
return decorator
@performance_stats(precision=2)
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
result = factorial(5)
print(result) # 输出:120Here the decorator takes a precision argument and returns a proper decorator.
3. Parameterized Authentication Decorator The login_required decorator checks user credentials against an allowed‑users dictionary.
users = {
"alice": "password123",
"bob": "secret456"
}
def login_required(allowed_users):
def decorator(func):
def wrapper(username, password, *args, **kwargs):
if username in allowed_users and allowed_users[username] == password:
print(f"User '{username}' authenticated")
return func(username, *args, **kwargs)
else:
print("Authentication failed")
return None
return wrapper
return decorator
@login_required(users)
def view_profile(username):
return f"Profile of user '{username}'"
result = view_profile("alice", "password123")
print(result) # 输出:Profile of user 'alice'
result = view_profile("bob", "wrongpass")
print(result) # 输出:NoneThe decorator receives a dictionary of allowed users and returns a proper decorator.
4. Parameterized Cache Decorator The memoize decorator caches function results with a configurable cache size.
from collections import OrderedDict
def memoize(cache_size=100):
cache = OrderedDict()
def decorator(func):
def wrapper(*args, **kwargs):
key = str(args) + str(kwargs)
if key not in cache:
print(f"Computing {func.__name__}({args}, {kwargs})")
result = func(*args, **kwargs)
cache[key] = result
if len(cache) > cache_size:
cache.popitem(last=False)
else:
print(f"Retrieving {func.__name__}({args}, {kwargs}) from cache")
return cache[key]
return wrapper
return decorator
@memoize(cache_size=10)
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
result = fibonacci(10)
print(result) # 输出:55This decorator accepts a cache size parameter and returns a proper decorator.
5. Parameterized File Logging Decorator The log_to_file decorator writes log messages to a specified file.
import logging
def log_to_file(log_file):
logging.basicConfig(filename=log_file, level=logging.DEBUG, format='%(asctime)s %(message)s')
def decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling function '{func.__name__}'")
result = func(*args, **kwargs)
logging.info(f"Function '{func.__name__}' returned {result}")
return result
return wrapper
return decorator
@log_to_file("example.log")
def debug_function():
return "Debug message"
debug_result = debug_function()
with open("example.log", "r") as file:
log_content = file.read()
print(log_content)The decorator takes a log file name and returns a proper decorator.
Conclusion The article presented five parameterized decorator patterns—logging, performance measurement, authentication, caching, and file logging—each with clear explanations and complete, ready‑to‑run Python code, illustrating how decorators can be customized for diverse functional requirements.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.