装饰器通过 @decorator_name 语法糖实现,常用于增强功能(如日志、权限校验)而不修改原代码。
1. 函数装饰器(无参数)
def logger(func):
def wrapper(*args, **kwargs):
print(f"开始执行: {func.__name__}")
result = func(*args, **kwargs) # 执行原函数
print(f"执行结束: {func.__name__}")
return result
return wrapper
@logger
def add(a, b):
return a + b
add(3, 5) # 输出执行日志
2. 函数装饰器(带参数)
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello {name}!")
greet("Alice") # 打印 3 次 Hello Alice!
3. 类装饰器
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
print(f"耗时: {time.time() - start:.2f}s")
return result
@Timer
def heavy_task():
time.sleep(2)
heavy_task() # 输出执行时间
装饰器的实战应用
1. 单例模式装饰器
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Database:
def __init__(self):
print("数据库连接已建立")
db1 = Database() # 输出 "数据库连接已建立"
db2 = Database() # 无输出
print(db1 is db2) # True
2. 权限校验
def login_required(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.is_authenticated:
raise PermissionError("需要登录")
return func(user, *args, **kwargs)
return wrapper
@login_required
def profile(user):
print(f"用户主页: {user.name}")
3. 性能分析
def benchmark(func):
@wraps(func)
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} 耗时: {time.time() - start:.4f}s")
return result
return wrapper
装饰器的注意事项
- 不要过度使用:装饰器会增加代码复杂度
- 处理参数:始终用
*args, **kwargs接收参数 - 调试问题:使用
@wraps保留原函数信息 - 线程安全:装饰器内部状态需考虑线程安全(如用锁)