简介
Python 装饰器是强大的工具,它允许开发者在不改变函数核心实现的情况下修改或增强函数。本教程将探讨堆叠多个装饰器的高级技术,展示如何通过分层不同的装饰器在 Python 编程中创建更复杂、更灵活的函数行为。
Python 装饰器是强大的工具,它允许开发者在不改变函数核心实现的情况下修改或增强函数。本教程将探讨堆叠多个装饰器的高级技术,展示如何通过分层不同的装饰器在 Python 编程中创建更复杂、更灵活的函数行为。
在 Python 中,装饰器是一种强大且灵活的方式,用于修改或增强函数或类,而无需直接更改其源代码。本质上,装饰器是将另一个函数作为参数,并返回该函数修改版本的函数。
def my_decorator(func):
def wrapper():
print("函数调用前的一些操作。")
func()
print("函数调用后的一些操作。")
return wrapper
@my_decorator
def say_hello():
print("你好!")
say_hello()
装饰器围绕现有函数进行包装,在原始函数执行之前或之后添加额外功能。
| 装饰器类型 | 描述 | 示例用例 |
|---|---|---|
| 函数装饰器 | 修改函数行为 | 日志记录、计时 |
| 类装饰器 | 修改类行为 | 单例模式 |
| 方法装饰器 | 修改方法行为 | 访问控制 |
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"函数 {func.__name__} 执行耗时 {end_time - start_time} 秒。")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(2)
print("慢速函数完成")
slow_function()
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(3)
def greet(name):
print(f"你好,{name}!")
greet("LabEx 用户")
通过理解这些基础知识,你将为探索 Python 中更高级的装饰器技术做好充分准备。LabEx 建议通过实践这些概念来提高熟练度。
装饰器链允许将多个装饰器应用于单个函数。当使用多个装饰器时,它们从下往上应用。
def decorator1(func):
def wrapper(*args, **kwargs):
print("装饰器1 - 函数调用前")
result = func(*args, **kwargs)
print("装饰器1 - 函数调用后")
return result
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("装饰器2 - 函数调用前")
result = func(*args, **kwargs)
print("装饰器2 - 函数调用后")
return result
return wrapper
@decorator1
@decorator2
def example_function():
print("在原始函数内部")
example_function()
import time
import functools
def log_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
return func(*args, **kwargs)
return wrapper
def timer_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"函数耗时 {end_time - start_time:.4f} 秒")
return result
return wrapper
@log_decorator
@timer_decorator
def complex_calculation(n):
return sum(i**2 for i in range(n))
complex_calculation(10000)
| 注意事项 | 描述 | 影响 |
|---|---|---|
| 顺序很重要 | 装饰器从下往上应用 | 改变函数行为 |
| 性能 | 多个装饰器可能会增加开销 | 考虑复杂度 |
| 可读性 | 太多装饰器会降低代码清晰度 | 谨慎使用 |
def validate_input(min_value=0, max_value=100):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for arg in args:
if not (min_value <= arg <= max_value):
raise ValueError(f"输入必须在 {min_value} 和 {max_value} 之间")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_input(min_value=10, max_value=50)
@log_decorator
def process_number(x):
return x * 2
process_number(30) ## 可行
## process_number(5) ## 引发 ValueError
functools.wraps 来保留函数元数据LabEx 建议通过实践装饰器链来掌握这一强大的 Python 技术。
def require_auth(role):
def decorator(func):
def wrapper(*args, **kwargs):
## 模拟认证检查
current_user = {
'username': 'admin',
'role': 'admin'
}
if current_user['role'] == role:
return func(*args, **kwargs)
else:
raise PermissionError("未经授权的访问")
return wrapper
return decorator
@require_auth('admin')
def delete_user(user_id):
print(f"正在删除用户 {user_id}")
delete_user(123) ## 管理员可操作
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(100)) ## 高效计算
import time
import functools
def performance_tracker(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行耗时 {end_time - start_time:.4f} 秒")
return result
return wrapper
@performance_tracker
def heavy_computation(n):
return sum(i**2 for i in range(n))
heavy_computation(1000000)
from functools import wraps
import time
def rate_limit(max_calls, time_frame):
calls = []
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
now = time.time()
calls[:] = [c for c in calls if now - c < time_frame]
if len(calls) >= max_calls:
raise Exception("速率限制已超出")
calls.append(now)
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limit(max_calls=3, time_frame=60)
def api_call():
print("API 调用成功")
## 演示速率限制
for _ in range(4):
try:
api_call()
except Exception as e:
print(e)
import logging
import functools
def log_calls(logger=None):
if logger is None:
logger = logging.getLogger(__name__)
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
logger.info(f"正在调用 {func.__name__}")
try:
result = func(*args, **kwargs)
logger.info(f"{func.__name__} 成功完成")
return result
except Exception as e:
logger.error(f"{func.__name__} 中的错误: {e}")
raise
return wrapper
return decorator
@log_calls()
def divide(a, b):
return a / b
divide(10, 2)
## divide(10, 0) ## 会记录错误
| 用例 | 主要目的 | 主要优点 |
|---|---|---|
| 认证 | 控制访问 | 安全性 |
| 缓存 | 优化性能 | 减少计算量 |
| 监控 | 跟踪性能 | 提供洞察 |
| 速率限制 | 防止滥用 | 资源保护 |
| 日志记录 | 跟踪函数调用 | 调试 |
functools.wraps 保留元数据LabEx 建议探索这些实际应用案例以提升你的 Python 编程技能。
通过理解如何在 Python 中堆叠多个装饰器,开发者可以创建更具模块化、可复用性和复杂性的代码。这项技术能够实现精确的函数修改,轻松地组合不同的装饰器,并提供一种简洁、易读的方式来扩展函数功能,同时又不会损害原始函数的核心逻辑。