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
结合场景再看三个关注点
- 字段声明即文档。
- 相等按字段值,适合测试断言。
- 需要冻结不可变可用
@dataclass(frozen=True)。
核心概念与准确模型
| 工具 | 可变 | 典型用途 |
|---|---|---|
dataclass | 默认可变 | 领域数据对象 |
namedtuple | 否 | 简单记录、可拆包 |
TypedDict | dict 形 | JSON 结构类型 |
field(default_factory=list)避免可变默认坑slots=True(3.10+)降内存
边界情况与反直觉行为
- 继承 dataclass 字段顺序规则需查文档。
- 可变字段默认必须
default_factory。 - frozen 后改字段抛 FrozenInstanceError。
常见误区
[!warning] 常见误区:dataclass 替代一切 OOP 错误理解:有数据就 dataclass 到底。
正确模型:富行为/不变量复杂时仍可手写类或加方法约束。
工程实践
- API schema 与领域模型分层
- 序列化边界明确(asdict/外部库)
- 与类型检查器一起用
本节总结
dataclass 消灭样板;namedtuple 保留元组基因。选更贴数据生命周期的那个。
自测题
- 为什么 list 字段要用 default_factory?
- frozen dataclass 解决什么?
参考答案
- 避免所有实例共享同一默认 list。
- 不可变记录,可哈希(字段可哈希时)防误改。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| dataclasses | 文档 | 官方 |
| collections.namedtuple | 文档 | namedtuple |