Python 内置装饰器通常分为两类:一类是语法内置、无需导入即可直接使用的原生核心装饰器,另一类来自官方标准库,导入对应模块即可使用。它们覆盖了面向对象封装、性能优化、代码简化、架构设计等场景。下面逐一讲解高频实用装饰器。
一、原生核心装饰器(无需导入)
这三个装饰器作用于类的方法,无需 import 直接使用。
1. @property
将类的方法伪装成属性访问,用于实现受控的 getter/setter/deleter,是 Python 实现“封装”特性的首选方式。例如,在配置类中做参数校验:- class AgentConfig:
- def __init__(self, temperature: float):
- self._temperature = temperature
- @property
- def temperature(self):
- return self._temperature
- @temperature.setter
- def temperature(self, value: float):
- if not 0 <= value <= 2:
- raise ValueError("temperature 必须在 0~2 之间")
- self._temperature = value
- config = AgentConfig(0.7)
- print(config.temperature) # 像属性一样读取
- config.temperature = 1.5 # 赋值时自动校验
复制代码
2. @classmethod
标记为类方法,第一个参数固定为 cls,无需实例化即可通过类名调用。常用于实现工厂模式(如 from_env 构造)。
3. @staticmethod
标记为静态方法,不接收 self 也不接收 cls,本质是放在类命名空间里的普通函数,适合存放与类相关但不需要实例上下文工具逻辑。例如:- class AgentConfig:
- @staticmethod
- def validate_temperature(value: float) -> bool:
- return 0 <= value <= 2
- print(AgentConfig.validate_temperature(0.7)) # True
复制代码
二、标准库高频内置装饰器
(一)dataclasses 模块:@dataclass
Python 3.7+ 引入的类装饰器,自动为数据类生成 __init__、__repr__、__eq__ 等方法,大幅减少样板代码。适用于定义配置、消息体、搜索结果等数据结构。- from dataclasses import dataclass
- from typing import Optional
- @dataclass
- class SearchResult:
- title: str
- url: str
- snippet: str
- score: Optional[float] = None
- result = SearchResult(title="华为最新手机", url="https://example.com", snippet="Mate 70 系列发布")
- print(result)
- # 输出:SearchResult(title='华为最新手机', url='https://example.com', snippet='Mate 70 系列发布', score=None)
复制代码
(二)functools 模块:工具装饰器集合
1. @functools.wraps
写自定义装饰器时的标配,保留原函数的元信息(函数名、文档字符串、参数签名)。只要自己写装饰器就必须用它:- import time
- from functools import wraps
- def timer(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- start = time.time()
- result = func(*args, **kwargs)
- print(f"{func.__name__} 耗时: {time.time()-start:.2f}s")
- return result
- return wrapper
- @timer
- def search(query: str):
- """搜索函数"""
- time.sleep(0.1)
- return f"搜索结果: {query}"
- print(search.__name__) # search(不加wraps会变成wrapper)
- print(search.__doc__) # 搜索函数
复制代码
2. @functools.lru_cache / @functools.cache
函数结果缓存装饰器,自动记住输入-输出映射,相同输入直接返回缓存结果,避免重复计算或重复调用。@cache(Python 3.9+)等价于 @lru_cache(maxsize=None);@lru_cache 可设置最大缓存数量,淘汰最少使用的缓存。适用于缓存搜索结果、RAG 检索结果等:- from functools import lru_cache
- @lru_cache(maxsize=100)
- def search_web(query: str) -> str:
- print(f"执行真实搜索: {query}")
- return f"{query} 的搜索结果"
- search_web("华为最新手机") # 执行真实搜索
- search_web("华为最新手机") # 直接返回缓存,不打印第二次
复制代码 注意:只能缓存参数可哈希的函数(参数为字符串、数字、元组等),列表、字典等不可哈希类型不能直接用。
3. @functools.total_ordering
类装饰器,只需实现 __eq__ 和一个比较方法(如 __lt__),自动补全 <=、>、>= 等全部比较运算符,常用于定义排序逻辑。
4. @functools.singledispatch
实现单分派泛函数——根据第一个参数的类型自动分发到不同处理逻辑,相当于按类型重载,适合统一入口但不同类型处理不同的函数。
(三)abc 模块:@abstractmethod
定义抽象基类的抽象方法,强制所有子类必须实现该方法,否则无法实例化。是接口规范和基类模板的核心工具。
(四)contextlib 模块:@contextmanager
将生成器函数转换为上下文管理器,替代手动编写 __enter__/__exit__,简化资源管理场景(如计时、临时目录):- from contextlib import contextmanager
- import time
- @contextmanager
- def timer(name: str):
- start = time.time()
- yield
- print(f"{name} 总耗时: {time.time()-start:.2f}s")
- with timer("搜索流程"):
- time.sleep(0.2)
复制代码
三、其他常用标准库装饰器
- @enum.unique(enum 模块):约束枚举类取值唯一,避免重复。
- @typing.overload(typing 模块):为函数定义多组类型重载注解,仅用于静态类型检查,运行时无实际效果。
- @asyncio.coroutine(asyncio 模块):旧版异步协程装饰器,已被 async/await 取代,仅兼容老代码。
四、项目高频总结
按使用频率排序:
数据结构:@dataclass(定义消息、配置、结果)
类设计:@property、@classmethod、@abstractmethod(基类与封装)
性能优化:@lru_cache(缓存重复调用)
自定义工具:@functools.wraps(写自己的装饰器)
资源管理:@contextmanager(上下文逻辑)
掌握这些内置装饰器能显著提升代码质量与开发效率,特别在构建 AI 智能体、数据分析工具等工程化项目中尤为实用。 |