专项练习 · 9 分钟阅读

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)

不可变记录

你的练习清单

常见问题

dataclass 会校验类型吗?

不会。注解表达意图,但自动生成的 __init__ 不会在运行时强制检查。

dataclass 可以有方法吗?

可以。它仍然是普通类,可以添加方法、属性,或在 __post_init__ 中做校验。

asdict 是浅拷贝吗?

它会递归转换 dataclass 值,但字段内部的可变对象仍可能共享。需要时请检查嵌套数据。

练习 dataclasses

12 道题,覆盖字段、默认值、相等比较、asdict 和 frozen 实例。

打开练习

继续阅读: