Python中的装饰器原理与应用
字数 848 2025-11-02 08:11:07
Python中的装饰器原理与应用
题目描述
装饰器(Decorator)是Python中一种高级语法特性,它允许在不修改原函数代码的情况下,为函数或类添加额外的功能(如日志记录、权限校验、性能监控等)。请解释装饰器的工作原理,并举例说明其具体应用场景。
1. 装饰器的基本概念
装饰器的本质是一个高阶函数,它接收一个函数作为参数,并返回一个新的函数(或可调用对象)。其核心思想是函数是第一类对象,即函数可以被赋值、传递或作为返回值。
关键点:
- Python中函数可以嵌套定义(闭包),内部函数可以访问外部函数的变量。
- 通过
@decorator_name语法糖,将装饰器应用到目标函数上。
2. 装饰器的实现步骤
步骤1:定义一个简单的装饰器
以下是一个统计函数执行时间的装饰器示例:
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:.2f}秒")
return result # 返回原函数的执行结果
return wrapper # 返回新函数
# 使用装饰器
@timer_decorator
def example_function(n):
time.sleep(n)
return "完成"
# 调用函数
example_function(2)
运行结果:
example_function 执行耗时: 2.00秒
步骤2:理解装饰器语法糖的作用
@timer_decorator 等价于以下代码:
def example_function(n):
time.sleep(n)
return "完成"
example_function = timer_decorator(example_function) # 手动替换原函数
3. 装饰器的进阶用法
(1)带参数的装饰器
若装饰器本身需要参数(如设置日志级别),需再嵌套一层函数:
def repeat(n): # 外层函数接收装饰器参数
def decorator(func): # 中层接收被装饰函数
def wrapper(*args, **kwargs):
for i in range(n):
result = func(*args, **kwargs)
print(f"第{i+1}次执行结果: {result}")
return result
return wrapper
return decorator
@repeat(3) # 重复执行3次
def greet(name):
return f"Hello, {name}"
greet("Alice")
输出:
第1次执行结果: Hello, Alice
第2次执行结果: Hello, Alice
第3次执行结果: Hello, Alice
(2)保留原函数的元信息
装饰器会覆盖原函数的__name__、__doc__等属性,需使用functools.wraps修复:
from functools import wraps
def timer_decorator(func):
@wraps(func) # 保留原函数的元信息
def wrapper(*args, **kwargs):
# ... 同上
return result
return wrapper
(3)类装饰器
通过实现__call__方法,类也可以作为装饰器:
class CountCalls:
def __init__(self, func):
self.func = func
self.call_count = 0
def __call__(self, *args, **kwargs):
self.call_count += 1
print(f"函数已被调用 {self.call_count} 次")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello() # 输出:函数已被调用 1 次
say_hello() # 输出:函数已被调用 2 次
4. 装饰器的应用场景
- 日志记录:自动记录函数调用参数和返回值。
- 权限校验:检查用户权限后再执行函数(如Web框架中的
@login_required)。 - 缓存:缓存函数结果以避免重复计算(如
functools.lru_cache)。 - 性能测试:统计函数执行时间(如示例中的
timer_decorator)。
5. 总结
- 装饰器基于闭包和函数式编程实现,是Python的元编程特性之一。
- 通过
@语法糖简化调用,但本质是函数替换。 - 注意装饰器嵌套时的执行顺序(从下往上)。
- 实际开发中应使用
functools.wraps保留原函数信息。