Python 的「内置装饰器」通常分为两类:
- 原生核心装饰器:Python 语法内置,无需导入即可直接使用,是面向对象编程的核心工具;
- 标准库装饰器:随 Python 官方标准库发布,无需额外安装,导入对应模块即可使用,覆盖性能优化、代码简化、架构设计等场景。
下面逐一讲解核心常用的装饰器。
一、原生核心装饰器(无需导入)
这三个是 Python 最基础的内置装饰器,全部作用于类的方法,无需 import 直接使用。
1. @property
作用 :将类的方法「伪装」成属性访问,用来实现受控的 getter / setter / deleter,封装属性的校验、计算、动态生成逻辑。
它是 Python 实现「封装」特性的首选方式,避免直接暴露类的内部变量。
示例(结合配置类场景):
python
class AgentConfig:
def __init__(self, temperature: float):
self._temperature = temperature
@property
def temperature(self):
"""读取时像访问属性一样:config.temperature"""
return self._temperature
@temperature.setter
def temperature(self, value: float):
"""设置参数时自动做范围校验"""
if not 0 <= value <= 2:
raise ValueError("temperature 必须在 0~2 之间")
self._temperature = value
使用方式:
python
config = AgentConfig(0.7)
print(config.temperature) # 像属性一样读取,不用写 get_temperature()
config.temperature = 1.5 # 像属性一样赋值,自动触发校验逻辑
2. @classmethod
作用 :标记为「类方法」,方法属于类本身而非实例。第一个参数固定为 cls(代表当前类),无需实例化即可通过类名直接调用,常用于实现多种构造方式 (工厂模式)。
你之前问过的 from_env 就是典型的类方法应用。
3. @staticmethod
作用 :标记为「静态方法」,它既不接收 self 也不接收 cls,本质是放在类命名空间里的普通工具函数 ,和类本身没有强制绑定,只是逻辑上归属于该类。
适合存放和类相关、但不需要访问类/实例属性的工具逻辑。
示例:
python
class AgentConfig:
@staticmethod
def validate_temperature(value: float) -> bool:
"""独立的参数校验工具,和实例/类无关"""
return 0 <= value <= 2
# 直接通过类调用,无需创建实例
print(AgentConfig.validate_temperature(0.7)) # True
二、标准库高频内置装饰器
这些装饰器来自 Python 官方标准库,无需额外安装,导入即可使用,是工程化项目的高频工具。
(一)dataclasses 模块:@dataclass
定位 :最常用的类装饰器(Python 3.7+ 加入),自动为数据类生成 __init__、__repr__、__eq__ 等魔术方法,大幅简化数据结构类的代码,避免重复的样板代码。
智能体场景:定义配置、消息体、搜索结果、工具返回值等数据结构的首选。
示例:
python
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 模块:工具装饰器集合
functools 是 Python 内置的高阶函数工具库,提供了多个工程化必备的装饰器。
1. @functools.wraps
作用 :写自定义装饰器时的标配,用来保留原函数的元信息 (函数名、文档字符串、参数签名等),避免装饰后的函数丢失原有属性。
只要你自己写装饰器,就必须用它。
示例:
python
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 检索结果、重复的大模型调用,减少重复请求。
示例:
python
from functools import lru_cache
@lru_cache(maxsize=100) # 最多缓存100个结果
def search_web(query: str) -> str:
"""模拟网络搜索,相同query不会重复请求"""
print(f"执行真实搜索: {query}")
return f"{query} 的搜索结果"
# 第一次调用会执行真实搜索
search_web("华为最新手机")
# 第二次相同输入,直接返回缓存,不会再打印"执行真实搜索"
search_web("华为最新手机")
注意:只能缓存参数可哈希的函数(参数是字符串、数字、元组等),列表、字典等不可哈希类型不能直接用。
3. @functools.total_ordering
作用 :类装饰器,只需给类实现 __eq__ 和一个比较方法(如 __lt__ 小于),自动补全剩余的 <=、>、>= 全部比较运算符,简化代码。
常用于给搜索结果、评分项定义排序逻辑。
4. @functools.singledispatch
作用 :实现单分派泛函数 ------根据函数第一个参数的类型,自动分发到不同的处理逻辑,相当于实现了「按类型重载」的效果。
适合写统一入口、但不同类型输入处理逻辑不同的函数。
(三)abc 模块:@abstractmethod
作用 :定义抽象基类的抽象方法,强制所有子类必须实现该方法,否则无法实例化。
是面向对象设计中「接口规范」「基类模板」的核心工具,你之前的 Agent 基类就是典型应用场景。
(四)contextlib 模块:@contextmanager
作用 :将生成器函数转换成上下文管理器 ,替代手动编写 __enter__ / __exit__ 方法,大幅简化上下文管理器的实现。
常用于资源管理(计时、临时目录、会话连接等)。
示例(计时上下文):
python
from contextlib import contextmanager
import time
@contextmanager
def timer(name: str):
start = time.time()
yield # 进入上下文执行代码,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(上下文逻辑)