数据类构建器 4 —— @dataclasses.dataclass详解

相关链接:
1. collections.namedtuple, typing.NamedTuple, @dataclasses.dataclass概述
2. collections.namedtuple详解
3. typing.NamedTuple详解
4. @dataclasses.dataclass详解


@dataclasses.dataclass 通过自动生成方法和类型注解支持,显著简化数据类的定义‌。其灵活性(如字段定制、可变性控制)和与静态检查工具的兼容性,使其成为替代传统类、字典或元组的理想选择‌。适用于需要结构化数据且兼顾开发效率的场景,尤其适合中大型项目中的核心数据建模‌。


一、@dataclasses.dataclass 核心功能‌

1. 自动生成特殊方法‌

  • 自动添加 __init____repr____eq__ 等方法,减少样板代码‌。
  • 示例
@dataclass  
class Point:  
    x: int  
    y: int  

等价于手动编写构造函数和字符串表示方法‌。

2. 类型注解支持‌

  • 强制声明字段类型(如 name: str),支持静态类型检查工具(如 mypy)‌。
  • 支持嵌套类型(如 List[Dict])和 Optional 注解‌。

3. 可变性控制‌

  • 默认字段可修改,设置 frozen=True 使实例不可变(类似 NamedTuple)‌。
@dataclass(frozen=True)  
class Config:  
    timeout: int  

二、装饰器接受的关键字参数

参数作用默认值备注
init作用是生成__init__True如果用户自己实现了__init__可以忽略该参数
repr作用是生成__repr__True如果用户自己实现了__repr__可以忽略该参数
eq作用是生成__eq__True如果用户自己实现了__eq__可以忽略该参数
order作用是生成__lt____le____gt____ge__False设为true时,需要自行定义用于比较的方法,否则抛出异常
unsafe_hash作用是生成__init__False语义复杂,不推荐使用
frozen防止意外更改实例False防止意外更改实例,相对安全,但不是绝对不可变

三、字段定制与高级配置‌

1. field() 函数‌

  • 接受的关键字参数
参数作用默认值
default字段的默认值_MISSING_TYPE1
default_factory不接受参数的函数,用于产生默认值_MISSING_TYPE
init把字段作为参数传给__init__方法True
repr在__repr__方法中使用字段True
compare在__eq__、__lt__等比较方法中使用字段True
hash在__hash__方法中使用字段计算哈希值None2
metadata用户定义的数据映射;@dataclass忽略该参数None
  • 示例
from dataclasses import dataclass, field  
@dataclass  
class User:  
    name: str  
    tags: list[str] = field(default_factory=list)  # 动态生成默认值‌  
    id: int = field(init=False)  # 不包含在构造函数中‌

2. 默认值与动态赋值‌

  • 默认值需通过 defaultdefault_factory 设置‌:
@dataclass  
class Data:  
    values: list = field(default_factory=lambda: [1, 2, 3])  

四、高级用法‌

1. 继承与扩展‌

  • 支持类继承,可结合 __post_init__ 添加初始化后逻辑‌:
@dataclass  
class Person:  
    name: str  
    age: int  
    def __post_init__(self):  
        if self.age < 0:  
            raise ValueError("Age cannot be negative")  

2. 序列化与转换‌

  • 通过 dataclasses.asdict()dataclasses.astuple() 转为字典/元组‌:
p = Person("Alice", 30)  
print(asdict(p))  # 输出:{'name': 'Alice', 'age': 30}  

五、特殊的伪类型

1. typing.ClassVar‌

  • 核心作用‌:标注类变量(Class Variable),表示该变量属于类级别而非实例级别。类型检查器会识别此注解,避免将类变量误判为实例变量‌。
    -‌ 语法示例‌
from typing import ClassVar  
class MyClass:  
    class_var: ClassVar[int] = 10  # 类变量,所有实例共享
    instance_data: list              # 实例变量,每个实例独立

#类变量通过类名访问
print(MyClass.class_var) # 输出: 10
  • 特点‌
    • 类变量通过类名直接访问(如 MyClass.class_var),所有实例共享同一份数据‌。
    • 若通过实例修改 ClassVar 变量,实际会创建同名实例属性,而非修改类变量‌。
  • 注意
    • 使用 ClassVar 时,需通过类名而非实例访问变量‌。
    • 如果尝试通过实例修改 ClassVar,实际会创建一个同名的实例属性,不会影响类变量本身‌。

2. typing.InitVar‌

  • 核心作用‌:在数据类(dataclass)中标记初始化参数,表示该参数仅在 __init__ 方法中使用,不作为实例属性保留。通常结合 __post_init__ 方法处理逻辑‌。
  • 语法示例‌
from dataclasses import dataclass, InitVar

@dataclass
class Person:
    name: str
    age: InitVar[int]  # 仅用于初始化,不保留为实例属性
    adult: bool = False

    def __post_init__(self, age: int):
        self.adult = age >= 18

p = Person("Alice", 20)
print(p.adult)  # 输出: True
print(hasattr(p, "age"))  # 输出: False  (age 不是实例属性)
  • 特点‌
    • InitVar 字段会被包含在生成的 __init__ 方法参数中,但不会生成对应的实例属性‌。
    • 需在 __post_init__ 方法中显式处理 InitVar 参数(如计算或验证逻辑)‌。
  • 注意
    • InitVar 标注的参数需在 __post_init__ 方法中显式处理‌。
    • 未标注为 InitVar 的参数默认会成为实例属性。

五、适用场景‌

1. 数据模型类‌

  • 替代手动定义 __init____repr__ 的类(如 ORM 实体、配置类)‌。

2. 复杂数据结构‌

  • 需动态默认值、继承或自定义初始化逻辑的场景‌。

3. 需要类型安全的可变数据‌

  • 结合类型注解和 IDE 提示提升代码可维护性‌。

<< 上一篇
3. typing.NamedTuple详解


  1. dataclass._MISSING_TYPE 是一个哨符值,表示未提供该参数。这样就可以把默认值设为经常需要使用的 None↩︎

  2. hash=None 表示仅当 compare=True 时才在 __hash__ 方法中使用字段。 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值