Python dataclass 练习指南:字段
dataclass 是一种简洁表达“这个类主要装数据”的方式。它会生成重复方法,但仍然只是普通 Python 类。理解它生成了什么、没有生成什么,既能减少样板,也能避免错误期待。
声明字段
写带注解的类属性。装饰器会用它们生成 __init__、__repr__ 和 __eq__。构造默认按位置传参,也可以使用关键字参数。自动生成的 repr 在日志和测试失败信息里很有用。
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
print(Point(2, 3))以数据为中心的类
把默认值放在正确顺序
带默认值的字段可以省略;没有默认值的字段仍必须提供,所以它不能跟在有默认值的字段后面。调整字段顺序,或者给前面的字段也加默认值。
from dataclasses import dataclass
@dataclass
class User:
name: str
active: bool = True
print(User("Ada"))
print(User("Grace", False))必填在前,可选在后
相等比较基于字段
两个 dataclass 实例的字段相等时,它们就相等,即使不是同一个对象。这在测试里很方便,但嵌套的可变字段仍遵循自己的相等规则。不要把相等和身份混为一谈。
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
print(Point(1, 2) == Point(1, 2))
print(Point(1, 2) is Point(1, 2))值相等,对象不同
用 asdict 转换
asdict 会递归地把 dataclass 实例转换成字典。列表、元组和嵌套 dataclass 也会被转换。它适合生成类 JSON 输出和断言,但返回的是副本,不是实时视图。
from dataclasses import dataclass, asdict
@dataclass
class Item:
name: str
price: float
print(asdict(Item("tea", 3.5)))普通字典
用 frozen 表示值对象
frozen=True 禁止构造后再给属性赋值。这让实例更适合共享和哈希,但不会深度冻结嵌套的可变值。它适合小型值对象,不应无差别替代所有类。
from dataclasses import dataclass
@dataclass(frozen=True)
class Item:
name: str
price: float
item = Item("tea", 3.5)
print(item.price)不可变记录
你的练习清单
- 给每个希望自动生成的字段加注解。
- 必填字段放在带默认值字段之前。
- 记住 __eq__ 比较的是字段值。
- 需要普通字典副本时使用 asdict。
- 小型不可变记录可以使用 frozen=True。
常见问题
dataclass 会校验类型吗?
不会。注解表达意图,但自动生成的 __init__ 不会在运行时强制检查。
dataclass 可以有方法吗?
可以。它仍然是普通类,可以添加方法、属性,或在 __post_init__ 中做校验。
asdict 是浅拷贝吗?
它会递归转换 dataclass 值,但字段内部的可变对象仍可能共享。需要时请检查嵌套数据。
练习 dataclasses
12 道题,覆盖字段、默认值、相等比较、asdict 和 frozen 实例。
继续阅读: