🐍Python 函数与面向对象

Dataclass 与 Enum

面试回答

常见问法

  • @dataclass 比普通类省了哪些样板代码?
  • frozen=Trueslots=Truekw_only=True 分别干什么?
  • NamedTupledataclassTypedDictpydantic.BaseModel 怎么选?
  • EnumIntEnumStrEnumauto() 分别什么场景?

回答

待补充:dataclass 是「数据容器类」的标准答案,Enum 是「有限取值」的标准答案,讲选型时要强调「是否需要验证、是否需要序列化、是否要性能」。

追问

  • dataclass(frozen=True) 为什么能让对象可哈希?
  • __post_init__ 用来做什么?
  • StrEnum(3.11+)和 str + Enum 有什么区别?
  • 为什么 Enum 成员不能被继承?

原理展开

  • @dataclass:自动生成 __init__ / __repr__ / __eq__,可选 __hash____slots__
  • 不可变:frozen=True → 冻结 setattr;结合可哈希,可做 dict key
  • __post_init__:在 __init__ 之后做校验或派生字段
  • field(default_factory=list):避免默认参数可变陷阱
  • NamedTuple:轻量级元组,但不可变、无 __post_init__
  • Enum:成员唯一、可迭代、== 比身份
  • StrEnum / IntEnum:直接和字符串/整数比较

易错点

  • [] 作默认值,多实例共享同一个列表(忘了 field(default_factory=...))
  • frozen=True 后还在 __post_init__ 里改字段,要用 object.__setattr__
  • dataclass 当 API 输入校验,其实应该用 pydantic
  • Enum(1) == 1 返回 False(除非用 IntEnum)

记忆技巧

  • dataclass 四开关:frozen / slots / kw_only / order
  • 数据容器选型:简单元组 → NamedTuple,属性对象 → dataclass,外部输入 → pydantic,类型字典 → TypedDict
  • Enum 口诀:有限取值全写清,需要字面量用 IntEnum / StrEnum