2026-03-09
Python
00
请注意,本文编写于 45 天前,最后修改于 44 天前,其中某些信息可能已经过时。

目录

一、什么是装饰器
二、装饰器原理解析
三、带参数的装饰器
四、使用 functools 保留函数信息
五、带参数的装饰器
六、实战:日志装饰器
七、实战:权限校验装饰器
八、实战:缓存装饰器
九、多个装饰器执行顺序
十、总结

在Python开发中,装饰器(Decorator)是一个非常强大的特性。

它可以在 不修改原函数代码的情况下扩展函数功能,被广泛应用于:

  • 日志记录
  • 权限校验
  • 性能统计
  • 缓存
  • Web框架(Flask / FastAPI)

本文将从 原理 → 实现 → 实战应用 逐步讲解Python装饰器。

一、什么是装饰器

装饰器本质上是 一个函数,用来包装另一个函数。

简单理解:

函数A → 传入装饰器 → 返回增强后的函数

示例:

python
def decorator(func): def wrapper(): print("函数执行前") func() print("函数执行后") return wrapper @decorator def hello(): print("hello world") hello()

输出:

函数执行前 hello world 函数执行后

二、装饰器原理解析

代码:

python
@decorator def hello(): print("hello")

实际上等价于:

python
def hello(): print("hello") hello = decorator(hello)

执行流程:

1 定义 hello 函数 2 调用 decorator(hello) 3 返回 wrapper 函数 4 hello 指向 wrapper

因此最终执行:

hello() → wrapper()

三、带参数的装饰器

很多时候函数会有参数,例如:

python
def hello(name): print(name)

此时装饰器需要支持参数。

示例:

python
def 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 执行后

四、使用 functools 保留函数信息

使用装饰器会导致函数信息丢失,例如:

python
print(hello.__name__)

输出:

wrapper

正确方式是使用 functools.wraps

示例:

python
from functools import wraps def decorator(func): @wraps(func) def wrapper(*args, **kwargs): print("before") return func(*args, **kwargs) return wrapper

这样可以保留:

函数名 docstring 注释

五、带参数的装饰器

有时候我们希望 装饰器本身也能传参。

示例:

python
def 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

六、实战:日志装饰器

开发中非常常见。

示例:

python
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"{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开发中经常使用。

示例:

python
def 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)

八、实战:缓存装饰器

python
def 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)

这样可以避免大量重复计算。

九、多个装饰器执行顺序

示例:

python
def 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装饰器的核心知识点:

  1. 装饰器本质是函数
  2. 用于增强函数功能
  3. 使用 *args, **kwargs 支持任意参数
  4. 使用 functools.wraps 保留函数信息
  5. 支持带参数装饰器
  6. 可以叠加多个装饰器

在实际开发中,装饰器常用于:

  • 日志
  • 权限控制
  • 性能统计
  • 缓存
  • Web框架

掌握装饰器可以大幅提升代码的 可复用性与优雅度。

本文作者:Dewar

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!