Python dataclass 与命名元组

dataclass 自动生成样板方法承载数据;namedtuple/TypedDict 提供轻量记录替代。

#type / concept #status / growing #tech / dev #resource / python #tech / lang / python

[!info] 关联笔记

Python dataclass 与命名元组

这个概念为什么出现

大量类只是“一堆字段 + 比较/展示”。手写 __init__/__repr__/__eq__ 易漏。dataclass 用声明生成这些样板;namedtuple 提供不可变记录。

[!abstract] 一句话理解 @dataclass 按字段声明生成初始化与常用方法;namedtuple 是轻量不可变元组子类。

最小可运行示例

先把示例放进业务场景,再看代码:

场景:订单行项目用 dataclass 建模

# order_line_dataclass.py
# 业务意图:表达订单行并计算行金额。
# 教学点:
# - @dataclass 字段;
# - 自动 repr/eq;
# - 方法仍可手写。

from dataclasses import dataclass


@dataclass
class OrderLine:
    sku: str
    qty: int
    unit_price_cents: int

    def line_total(self) -> int:
        return self.qty * self.unit_price_cents


def main() -> None:
    a = OrderLine("SKU-1", 2, 500)
    b = OrderLine("SKU-1", 2, 500)
    print(a)
    print("eq:", a == b)
    print("total:", a.line_total())


if __name__ == "__main__":
    main()

建议运行:

python order_line_dataclass.py

期望输出:

OrderLine(sku='SKU-1', qty=2, unit_price_cents=500)
eq: True
total: 1000

结合场景再看三个关注点

  1. 字段声明即文档
  2. 相等按字段值,适合测试断言。
  3. 需要冻结不可变可用 @dataclass(frozen=True)

核心概念与准确模型

工具可变典型用途
dataclass默认可变领域数据对象
namedtuple简单记录、可拆包
TypedDictdict 形JSON 结构类型
  • field(default_factory=list) 避免可变默认坑
  • slots=True(3.10+)降内存

边界情况与反直觉行为

  1. 继承 dataclass 字段顺序规则需查文档。
  2. 可变字段默认必须 default_factory
  3. frozen 后改字段抛 FrozenInstanceError。

常见误区

[!warning] 常见误区:dataclass 替代一切 OOP 错误理解:有数据就 dataclass 到底。
正确模型:富行为/不变量复杂时仍可手写类或加方法约束。

工程实践

  • API schema 与领域模型分层
  • 序列化边界明确(asdict/外部库)
  • 与类型检查器一起用

本节总结

dataclass 消灭样板;namedtuple 保留元组基因。选更贴数据生命周期的那个。

自测题

  1. 为什么 list 字段要用 default_factory?
  2. frozen dataclass 解决什么?
参考答案
  1. 避免所有实例共享同一默认 list。
  2. 不可变记录,可哈希(字段可哈希时)防误改。

延伸阅读与资料来源

资料类型支撑内容
dataclasses文档官方
collections.namedtuple文档namedtuple
创建于 2026/7/15 更新于 2026/7/15