Python @dataclass 使用说明

@dataclass 是 Python 标准库 dataclasses 提供的装饰器,用来快速定义“主要用于保存数据的类”。

它可以自动生成 __init____repr____eq__ 等常用方法,让代码更简洁。

1. 为什么需要 @dataclass

如果不用 @dataclass,定义一个保存配置的类通常需要手写 __init__

class Context:
    def __init__(self, model, model_provider):
        self.model = model
        self.model_provider = model_provider

使用 @dataclass 后,可以简化为:

from dataclasses import dataclass

@dataclass
class Context:
    model: str
    model_provider: str

Python 会自动帮你生成初始化方法,所以可以直接这样创建对象:

context = Context(
    model="qwen3.5-plus",
    model_provider="openai",
)

2. 基本语法

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int

创建对象:

user = User(name="Alice", age=18)
print(user)

输出类似:

User(name='Alice', age=18)

3. 字段类型标注

@dataclass 通常和类型标注一起使用,支持 Python 所有内置和标准库类型。

基本类型

from dataclasses import dataclass

@dataclass
class Product:
    name: str           # 字符串
    price: float        # 浮点数
    stock: int          # 整数
    on_sale: bool       # 布尔值

List / Dict / Tuple / Set

from dataclasses import dataclass, field
from typing import List, Dict, Tuple, Set

@dataclass
class Order:
    items: List[str]                    # 字符串列表
    quantities: Dict[str, int]          # 字符串到整数的字典
    tags: Set[str]                      # 字符串集合
    coordinates: Tuple[float, float]    # 固定长度的元组

注意:ListDict 等默认值不能直接写 = [],要用 field(default_factory=...)

@dataclass
class Order:
    items: List[str] = field(default_factory=list)
    metadata: Dict[str, str] = field(default_factory=dict)

Python 3.9+ 内置写法(不需要 import typing)

@dataclass
class Order:
    items: list[str]             # 等价于 List[str]
    metadata: dict[str, int]     # 等价于 Dict[str, int]
    tags: set[str]               # 等价于 Set[str]

可选类型

from dataclasses import dataclass

@dataclass
class Config:
    api_key: str | None = None      # 可以是 str,也可以是 None(Python 3.10+)
    base_url: str | None = None

Python 3.9 及以下用 Optional

from typing import Optional

@dataclass
class Config:
    api_key: Optional[str] = None

嵌套 dataclass

@dataclass
class Address:
    city: str
    country: str

@dataclass
class User:
    name: str
    age: int
    address: Address    # 嵌套另一个 dataclass

使用:

user = User(
    name="Alice",
    age=18,
    address=Address(city="Beijing", country="China"),
)
print(user.address.city)  # Beijing

综合示例

from dataclasses import dataclass, field
from typing import List, Dict

@dataclass
class ModelConfig:
    model: str                                      # 必填字符串
    temperature: float = 0.7                        # 浮点数带默认值
    max_tokens: int = 1024                          # 整数带默认值
    stop_sequences: List[str] = field(default_factory=list)  # 字符串列表
    extra_params: Dict[str, str] = field(default_factory=dict)  # 字典
    api_key: str | None = None                      # 可选字符串

类型标注主要用于代码提示、静态检查和可读性,不会默认强制运行时类型校验。

4. 默认值

字段可以设置默认值:

@dataclass
class Config:
    model: str
    temperature: float = 0.7
    max_tokens: int = 1024

使用时可以只传必填字段:

config = Config(model="qwen3.5-plus")
print(config.temperature)  # 0.7

注意:没有默认值的字段要写在有默认值字段的前面。

5. 可选字段

如果一个字段可以是字符串,也可以为空,可以这样写:

@dataclass
class Context:
    api_key: str | None = None
    base_url: str | None = None

含义是:

  • api_key 可以是 str,也可以是 None
  • 默认值是 None

6. 当前代码中的用法

5.configurable_model.py 中,Context 用来保存运行时模型配置:

@dataclass
class Context:
    model: str
    model_provider: str
    api_key: str | None = None
    base_url: str | None = None

它表示一次 Agent 调用时可以传入这些信息:

  • model:模型名称,例如 "qwen3.5-plus"
  • model_provider:模型提供方,例如 "openai"
  • api_key:模型服务的 API Key
  • base_url:模型服务的接口地址

调用时可以这样传入:

context = Context(
    model="qwen3.5-plus",
    model_provider="openai",
    api_key=DASHSCOPE_API_KEY,
    base_url=DASHSCOPE_BASE_URL,
)

然后中间件可以通过 request.runtime.context 读取这些配置:

context = request.runtime.context

model = init_chat_model(
    context.model,
    model_provider=context.model_provider,
    api_key=context.api_key,
    base_url=context.base_url,
)

这样就能在运行时动态切换模型。

7. @dataclass 自动生成了什么

定义:

@dataclass
class User:
    name: str
    age: int

大致等价于自动生成:

class User:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"User(name={self.name!r}, age={self.age!r})"

    def __eq__(self, other):
        return self.name == other.name and self.age == other.age

所以 @dataclass 可以减少大量模板代码。

8. 常见适用场景

@dataclass 适合用来定义结构化数据:

  • 配置对象
  • 请求上下文
  • 用户信息
  • 商品信息
  • 任务参数
  • 中间状态
  • API 返回结果的数据结构

例如:

@dataclass
class TaskConfig:
    task_id: str
    model: str
    timeout: int = 30

9. 什么时候不适合用 @dataclass

如果一个类主要负责复杂行为,而不是保存数据,就不一定适合使用 @dataclass

例如:

  • 需要复杂初始化逻辑
  • 需要继承复杂框架基类
  • 主要封装业务行为
  • 需要严格运行时校验

这类场景可能更适合普通类,或者使用 Pydantic 这类数据校验库。

10. 小结

@dataclass 可以理解为:

用更少的代码定义一个清晰的数据容器类。

它最常见的价值是:

  • 自动生成初始化方法
  • 自动生成可读的打印结果
  • 减少重复代码
  • 让配置和上下文对象更清晰

在当前 LangChain 示例中,Context 使用 @dataclass 是为了方便保存并传递运行时模型配置。

作者:海马  创建时间:2026-06-24 16:07
最后编辑:海马  更新时间:2026-07-01 20:05
上一篇:
下一篇: