装饰器(Decorator)
装饰器(Decorator)是 Python 中一种强大的语法特性,它允许在不修改原函数或类代码的情况下,动态地增强其功能。理解装饰器的核心在于掌握 函数作为一等公民 和 闭包 的概念。以下是逐步深入的分析:
一、装饰器的本质
装饰器的核心是一个 高阶函数,它接收一个函数作为参数,并返回一个新函数(或类)。
通过 @decorator
语法糖,Python 自动将原函数传递给装饰器,并用返回的新函数替换原函数。
def decorator(func):
def wrapper(*args, **kwargs):
print("Before calling", func.__name__)
result = func(*args, **kwargs)
print("After calling", func.__name__)
return result
return wrapper
@decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# Before calling say_hello
# Hello!
# After calling say_hello
二、装饰器的工作原理
-
语法糖的等价形式
@decorator
等价于say_hello = decorator(say_hello)
,即装饰器返回的wrapper
函数替换了原函数。 -
闭包与作用域
装饰器内部定义的wrapper
函数捕获了外层变量func
,形成闭包。这使得wrapper
可以在调用时访问到原函数。 -
保留原函数元信息
使用functools.wraps(func)
装饰wrapper
函数,可以保留原函数的__name__
、__doc__
等元信息。
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# ...
return wrapper
三、带参数的装饰器
若装饰器需要接受参数,需再嵌套一层函数,形成 三层嵌套结构:
def repeat(n):
def outer_wrapper(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return outer_wrapper
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
# 输出:
# Hello, Alice!
# Hello, Alice!
# Hello, Alice!
四、类装饰器
类也可以作为装饰器,只需实现 __call__
方法:
class Logger:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(f"Calling {self.func.__name__}")
return self.func(*args, **kwargs)
@Logger
def calculate(a, b):
return a + b
print(calculate(2, 3))
# 输出:
# Calling calculate
# 5
五、装饰器的应用场景
- 日志记录:自动记录函数调用信息。
- 性能测试:统计函数执行时间。
- 权限校验:检查用户权限后再执行函数。
- 缓存:实现缓存机制(如
functools.lru_cache
)。 - 路由注册:Web 框架(如 Flask)用装饰器注册 URL 路由。
六、注意事项
-
装饰器顺序:多个装饰器按从下到上的顺序应用。
@decorator1 @decorator2 def func(): ... # 等价于 func = decorator1(decorator2(func))
-
装饰器副作用:装饰器可能修改函数签名或引入隐藏行为,需谨慎设计。
-
调试问题:使用
functools.wraps
保留原函数信息,便于调试。
七、总结
装饰器的核心思想是 函数组合,通过将功能模块化,实现代码复用和解耦。深入理解装饰器需要掌握:
- 函数作为对象传递
- 闭包与作用域
- 可变参数(
*args
,**kwargs
) - 元编程思想
掌握装饰器能让代码更简洁、可维护性更高,是 Python 高级编程的必备技能。