Python 装饰器高级用法
外观
Python装饰器高级用法[编辑 | 编辑源代码]
装饰器是Python函数式编程中的核心概念之一,它允许在不修改原函数代码的情况下,动态地扩展函数的行为。装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。本节将深入探讨装饰器的高级用法,包括带参数的装饰器、类装饰器、装饰器堆叠以及实际应用场景。
1. 装饰器基础回顾[编辑 | 编辑源代码]
装饰器的基本语法如下:
def decorator(func):
def wrapper(*args, **kwargs):
# 前置操作
result = func(*args, **kwargs)
# 后置操作
return result
return wrapper
@decorator
def target_function():
pass
当调用target_function()
时,实际上执行的是decorator(target_function)()
。
2. 带参数的装饰器[编辑 | 编辑源代码]
装饰器本身也可以接受参数,这需要再嵌套一层函数:
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"Hello, {name}!")
greet("Alice")
输出:
Hello, Alice! Hello, Alice! Hello, Alice!
3. 类装饰器[编辑 | 编辑源代码]
类也可以作为装饰器,只需实现__call__
方法:
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} executed in {end-start:.4f}s")
return result
@Timer
def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
print(factorial(5))
输出:
factorial executed in 0.0001s factorial executed in 0.0002s ... 120
4. 装饰器堆叠[编辑 | 编辑源代码]
多个装饰器可以堆叠使用,执行顺序是从下往上:
@decorator1
@decorator2
@decorator3
def function():
pass
等价于:
function = decorator1(decorator2(decorator3(function)))
5. 保留元信息[编辑 | 编辑源代码]
使用functools.wraps
保留原函数的元信息:
from functools import wraps
def log_execution(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Executing {func.__name__}")
return func(*args, **kwargs)
return wrapper
6. 实际应用案例[编辑 | 编辑源代码]
6.1 权限验证[编辑 | 编辑源代码]
def requires_admin(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.is_admin:
raise PermissionError("Admin rights required")
return func(user, *args, **kwargs)
return wrapper
6.2 缓存装饰器[编辑 | 编辑源代码]
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
7. 高级模式:装饰器工厂[编辑 | 编辑源代码]
装饰器工厂可以动态生成装饰器:
def validate_input(*validators):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for i, (arg, validator) in enumerate(zip(args, validators)):
if not validator(arg):
raise ValueError(f"Argument {i} invalid")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_input(lambda x: x > 0, lambda y: isinstance(y, str))
def process_data(num, text):
return text * num
8. 执行流程可视化[编辑 | 编辑源代码]
9. 数学表达[编辑 | 编辑源代码]
装饰器的数学本质可以表示为: 其中表示函数组合。
10. 最佳实践[编辑 | 编辑源代码]
- 始终使用
functools.wraps
保留元信息 - 避免在装饰器中修改传入的参数
- 装饰器的逻辑应保持简洁单一
- 考虑使用类装饰器处理复杂状态
通过掌握这些高级技巧,你可以创建出更灵活、更强大的装饰器,显著提升代码的可重用性和可维护性。