装饰器(Decorator)是 Python 中一种强大的语法特性,允许在不修改原始代码的情况下动态扩展函数或类的功能。以下是其语法、用法、优缺点及常见使用场景的详细说明:
装饰器本质上是一个可调用对象(函数或类),接受一个函数作为输入,返回一个新的函数(或类)。
def decorator(func):
def wrapper(*args, **kwargs):
# 前置操作(如日志、权限校验)
result = func(*args, **kwargs) # 调用原函数
# 后置操作(如数据处理、清理)
return result
return wrapper
@decorator # 等价于 func = decorator(func)
def func():
pass
通过嵌套函数实现装饰器参数传递:
def decorator_with_args(param):
def actual_decorator(func):
def wrapper(*args, **kwargs):
print(f"Decorator param: {param}")
return func(*args, **kwargs)
return wrapper
return actual_decorator
@decorator_with_args("config")
def func():
pass
通过实现 __call__
方法让类的实例成为装饰器:
class ClassDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Class decorator")
return self.func(*args, **kwargs)
@ClassDecorator
def func():
pass
执行顺序:从下往上(靠近函数的装饰器先执行):
@decorator1
@decorator2
def func():
pass
# 等价于 func = decorator1(decorator2(func))
@
语法让代码更清晰,逻辑分离更明确。调试困难:装饰器可能隐藏原函数的元信息(如 __name__
、文档字符串),需用 functools.wraps
修复:
from functools import wraps
def decorator(func):
@wraps(func) # 保留原函数元信息
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
过度嵌套:多层装饰器可能导致代码可读性下降。
隐式行为:装饰器的副作用可能导致代码行为难以预测(尤其是第三方装饰器)。
import time
from functools import wraps
def log_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Function {func.__name__} took {end - start:.2f} seconds to run.")
return result
return wrapper
@log_time
def example_function(n):
sum = 0
for i in range(n):
sum += i
return sum
result = example_function(1000000)
print(f"Result: {result}")
运行结果:
Function example_function took 0.07 seconds to run.
Result: 499999500000
from functools import wraps
class User:
def __init__(self, authenticated):
self.is_authenticated = authenticated
def login_required(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.is_authenticated:
raise PermissionError("User not logged in")
return func(user, *args, **kwargs)
return wrapper
@login_required
def admin_dashboard(user):
return "Welcome to the admin dashboard!"
user = User(authenticated=True)
print(admin_dashboard(user))
user = User(authenticated=False)
try:
print(admin_dashboard(user))
except PermissionError as e:
print(e)
运行结果:
Welcome to the admin dashboard!
User not logged in
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
运行结果:
55
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello World"
@app.route("/about")
def about():
return "About Page"
if __name__ == "__main__":
app.run(debug=True)
运行结果:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 123-456-789
访问 http://127.0.0.1:5000/
将显示 “Hello World”,访问 http://127.0.0.1:5000/about
将显示 “About Page”。
from functools import wraps
import time
import tracemalloc
def performance_monitor(func):
@wraps(func)
def wrapper(*args, **kwargs):
tracemalloc.start()
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Function {func.__name__} executed in {end_time - start_time:.2f}s")
print(f"Memory usage: Current = {current / 10**6:.2f}MB, Peak = {peak / 10**6:.2f}MB")
return result
return wrapper
@performance_monitor
def memory_intensive_function():
data = [i for i in range(1000000)]
return len(data)
memory_intensive_function()
运行结果:
Function memory_intensive_function executed in 0.07s
Memory usage: Current = 7.63MB, Peak = 7.63MB
functools.wraps
保留元信息,避免深层嵌套。装饰器是 Python 高阶编程的核心工具之一,合理使用可以显著提升代码质量和可维护性。