Z
ZHANK
数据结构

数据类 dataclass

用 @dataclass 替代手写 __init__、field 默认值、冻结实例

dataclasses 数据类

Python 3.7+ 引入的 dataclass 装饰器,让你用更少代码定义数据类。

学完本章你将掌握: 基本用法、默认值、不可变、field 选项。


一、普通类 vs dataclass

python
# 普通类:需要手写 __init__ __repr__ __eq__ ...
class Person_old:
    def __init__(self, name, age):
        self.name, self.age = name, age

# dataclass:一行装饰器搞定
from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

p1 = Person("小明", 20)
p2 = Person("小明", 20)
print(p1)              # Person(name='小明', age=20)
print(p1 == p2)        # True(自动生成 __eq__)

二、默认值与字段

python
@dataclass
class Student:
    name: str
    age: int
    grade: str = "一年级"           # 有默认值的字段
    scores: list[int] = None        # ⚠️ 可变默认值要用 field

# ⚠️ 可变默认值用 field(default_factory=...)
from dataclasses import field

@dataclass
class Student:
    name: str
    scores: list[int] = field(default_factory=list)

s1 = Student("小明")
s1.scores.append(90)
s2 = Student("小红")
s2.scores.append(85)
print(s1.scores)  # [90](不会互相影响!)

三、不可变数据类

python
@dataclass(frozen=True)
class Point:
    x: int
    y: int

p = Point(10, 20)
# p.x = 30  # ❌ FrozenInstanceError

四、field 常用参数

python
@dataclass
class Config:
    name: str
    timeout: int = field(default=30, metadata={"unit": "秒"})
    debug: bool = field(default=False, repr=False)  # repr 中隐藏

五、实战对比

python
# 不用 dataclass(~15 行)
class Task:
    def __init__(self, title, done=False, priority=0):
        self.title, self.done, self.priority = title, done, priority
    def __repr__(self): return f"Task({self.title!r})"
    def __eq__(self, o): return (self.title,self.done)==(o.title,o.done)

# 用 dataclass(~5 行)
@dataclass
class Task:
    title: str
    done: bool = False
    priority: int = 0

小结

  1. @dataclass 自动生成 __init__ __repr__ __eq__
  2. 可变默认值用 field(default_factory=list)
  3. frozen=True 创建不可变数据类
  4. 相比 namedtuple,dataclass 更灵活