在Python开发中,装饰器(Decorator)是一个非常强大的特性。
它可以在 不修改原函数代码的情况下扩展函数功能,被广泛应用于:
本文将从 原理 → 实现 → 实战应用 逐步讲解Python装饰器。
装饰器本质上是 一个函数,用来包装另一个函数。
简单理解:
函数A → 传入装饰器 → 返回增强后的函数
示例:
pythondef decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@decorator
def hello():
print("hello world")
hello()
输出:
函数执行前 hello world 函数执行后
代码:
python@decorator
def hello():
print("hello")
实际上等价于:
pythondef hello():
print("hello")
hello = decorator(hello)
执行流程:
1 定义 hello 函数 2 调用 decorator(hello) 3 返回 wrapper 函数 4 hello 指向 wrapper
因此最终执行:
hello() → wrapper()
很多时候函数会有参数,例如:
pythondef hello(name):
print(name)
此时装饰器需要支持参数。
示例:
pythondef decorator(func):
def wrapper(*args, **kwargs):
print("执行前")
result = func(*args, **kwargs)
print("执行后")
return result
return wrapper
@decorator
def hello(name):
print(f"hello {name}")
hello("Tom")
输出:
执行前 hello Tom 执行后
使用装饰器会导致函数信息丢失,例如:
pythonprint(hello.__name__)
输出:
wrapper
正确方式是使用 functools.wraps。
示例:
pythonfrom functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("before")
return func(*args, **kwargs)
return wrapper
这样可以保留:
函数名 docstring 注释
有时候我们希望 装饰器本身也能传参。
示例:
pythondef log(level):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"log level: {level}")
return func(*args, **kwargs)
return wrapper
return decorator
使用:
python@log("INFO")
def hello():
print("hello")
hello()
执行流程:
log("INFO") → decorator → wrapper
开发中非常常见。
示例:
pythonimport 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"{func.__name__} 执行时间: {end-start:.4f}s")
return result
return wrapper
@log_time
def slow_function():
time.sleep(1)
slow_function()
输出:
slow_function 执行时间: 1.0001s
在Web开发中经常使用。
示例:
pythondef require_login(func):
def wrapper(user):
if not user.get("login"):
raise Exception("未登录")
return func(user)
return wrapper
@require_login
def profile(user):
print("用户中心")
user = {"login": True}
profile(user)
pythondef cache(func):
data = {}
def wrapper(n):
if n in data:
return data[n]
result = func(n)
data[n] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
这样可以避免大量重复计算。
示例:
pythondef a(func):
def wrapper():
print("A before")
func()
print("A after")
return wrapper
def b(func):
def wrapper():
print("B before")
func()
print("B after")
return wrapper
@a
@b
def hello():
print("hello")
hello()
执行顺序:
A before B before hello B after A after
规则:
从下往上装饰 从上往下执行
Python装饰器的核心知识点:
*args, **kwargs 支持任意参数functools.wraps 保留函数信息在实际开发中,装饰器常用于:
掌握装饰器可以大幅提升代码的 可复用性与优雅度。
本文作者:Dewar
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!