简介
Python 装饰器是强大的工具,使开发者能够在不直接更改函数源代码的情况下修改或增强函数。本教程探讨用于处理多个参数的高级装饰器技术,为开发者提供创建更灵活、动态的函数包装器的全面策略。
装饰器基础
什么是装饰器?
在 Python 中,装饰器是一种强大且优雅的方式,用于在不直接更改函数或类的源代码的情况下对其进行修改或增强。它允许你用另一个函数来包装一个函数,动态地添加额外的功能。
基本装饰器语法
一个基本的装饰器遵循以下基本结构:
def my_decorator(func):
def wrapper():
## 在原始函数执行之前执行的代码
func() ## 调用原始函数
## 在原始函数执行之后执行的代码
return wrapper
@my_decorator
def original_function():
print("原始函数正在运行")
简单装饰器示例
让我们演示一个简单的性能计时装饰器:
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()
装饰器工作流程
graph TD
A[原始函数] --> B[装饰器包装器]
B --> C{预处理}
C --> D[调用原始函数]
D --> E{后处理}
E --> F[返回结果]
装饰器的关键特性
| 特性 | 描述 |
|---|---|
| 可重用性 | 可以应用于多个函数 |
| 非侵入性 | 不修改原始函数代码 |
| 可扩展性 | 可以添加多层功能 |
常见用例
装饰器通常用于:
- 日志记录
- 性能测量
- 认证
- 缓存
- 输入验证
通过理解这些基础知识,你就可以准备好在 LabEx Python 编程课程中探索更高级的装饰器技术了。
带参数的装饰器
理解装饰器参数
装饰器可以接受参数以提供更大的灵活性和定制性。创建带参数的装饰器主要有两种方式:
- 接受函数参数的装饰器
- 接受自身参数的装饰器
接受函数参数的装饰器
def validate_args(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, int):
raise TypeError(f"预期为整数,得到的是 {type(arg)}")
return func(*args, **kwargs)
return wrapper
@validate_args
def add_numbers(a, b):
return a + b
print(add_numbers(3, 4)) ## 正常工作
## print(add_numbers(3, "4")) ## 引发TypeError
带自定义参数的装饰器
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 greet(name):
print(f"你好,{name}!")
greet("LabEx")
装饰器参数流程
graph TD
A[装饰器参数] --> B[装饰器工厂]
B --> C[装饰器包装器]
C --> D[原始函数]
D --> E[返回结果]
装饰器参数类型
| 参数类型 | 描述 | 示例 |
|---|---|---|
| 位置参数 | 固定位置的参数 | @repeat(3) |
| 关键字参数 | 命名参数 | @validate(min_length=5) |
| 混合参数 | 位置参数和关键字参数的组合 | @custom_decorator(10, strict=True) |
高级参数处理
def log_calls(log_level='INFO'):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{log_level}] 调用 {func.__name__}")
return func(*args, **kwargs)
return wrapper
return decorator
@log_calls(log_level='DEBUG')
def complex_calculation(x, y):
return x * y
complex_calculation(5, 6)
最佳实践
- 对复杂的参数处理使用嵌套函数
- 使用
functools.wraps保留原始函数的元数据 - 保持装饰器逻辑简洁且专注
- 优雅地处理不同的参数场景
通过掌握带参数的装饰器,你将在 Python 中解锁强大的元编程技术,提升你在 LabEx 编程项目中代码的灵活性和可重用性。
实用装饰器示例
缓存装饰器
from functools import lru_cache
@lru_cache(maxsize=100)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(100)) ## 计算速度极快
认证装饰器
def authenticate(role='user'):
def decorator(func):
def wrapper(*args, **kwargs):
user_role = 'admin' ## 模拟认证
if user_role == role:
return func(*args, **kwargs)
else:
raise PermissionError("未经授权的访问")
return wrapper
return decorator
@authenticate(role='admin')
def delete_system_files():
print("系统文件已删除")
delete_system_files()
性能监测装饰器
import time
import functools
def performance_monitor(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} 执行耗时 {end - start:.4f} 秒")
return result
return wrapper
@performance_monitor
def complex_computation(n):
return sum(i**2 for i in range(n))
complex_computation(1000000)
装饰器工作流程
graph TD
A[装饰器] --> B[输入验证]
B --> C[性能跟踪]
C --> D[认证]
D --> E[缓存]
E --> F[原始函数]
实际应用中的装饰器
| 用例 | 描述 | 示例 |
|---|---|---|
| 日志记录 | 跟踪函数调用 | 捕获方法调用 |
| 速率限制 | 控制函数执行频率 | API 请求管理 |
| 输入验证 | 确保数据完整性 | 类型和范围检查 |
| 重试机制 | 自动错误恢复 | 网络请求处理 |
带指数退避的重试装饰器
import time
from functools import wraps
def retry(max_attempts=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise
wait = delay * (2 ** attempts)
time.sleep(wait)
return wrapper
return decorator
@retry(max_attempts=3, delay=2)
def unstable_network_request():
## 模拟网络请求
import random
if random.random() < 0.7:
raise ConnectionError("网络不稳定")
return "成功"
unstable_network_request()
高级装饰器技术
- 组合多个装饰器
- 创建基于类的装饰器
- 使用
functools.wraps保留元数据 - 处理复杂的参数场景
通过探索这些实际示例,你将深入了解装饰器在 LabEx Python 编程中的多功能性,从而实现更健壮、高效的代码设计。
总结
通过掌握带多个参数的装饰器,Python 开发者可以创建更复杂且可复用的代码结构。本教程展示了如何实现能接受各种参数类型、增强函数行为并提升整体代码模块化和可维护性的复杂装饰器。



