一、@dataclass
@dataclass是 Python 3.7 引入的一个装饰器,用于自动生成类的样板代码。只需要声明字段和类型,它自动生成:
| 自动生成 | 说明 |
|---|---|
__init__ | 构造方法 |
__repr__ | 字符串表示 |
__eq__ | 相等比较 |
from dataclasses import dataclass @dataclass class User: name: str age: int email: str = "" # 自动生成 __init__,可以直接创建实例 u = User("Alice", 25) print(u) # User(name='Alice', age=25, email='') print(u == User("Alice", 25)) # True如果没有@dataclass,需要手写:
class User: def __init__(self, name, age, email=""): self.name = name self.age = age self.email = email def __repr__(self): return f"User(name={self.name!r}, age={self.age!r}, email={self.email!r})" def __eq__(self, other): if not isinstance(other, User): return NotImplemented return (self.name, self.age, self.email) == (other.name, other.age, other.email)@dataclass把上面这些样板代码全省了。
二、基本语法
from dataclasses import dataclass @dataclass class 类名: 字段名: 类型 字段名: 类型 = 默认值规则:
字段必须有类型注解
有默认值的字段必须放在无默认值字段的后面
支持所有 Python 类型(
int、str、list、自定义类等)
@dataclass class Product: name: str # 必填 price: float # 必填 stock: int = 0 # 默认值 tags: list = None # 默认值(可变对象要用 field,后面讲)三、自动生成的方法
1.__init__
@dataclass class Point: x: int y: int p = Point(1, 2) # 自动生成的 __init__(self, x, y) print(p.x, p.y) # 1 22.__repr__
p = Point(1, 2) print(p) # Point(x=1, y=2)调试时非常方便,不用手动写__repr__。
3.__eq__
p1 = Point(1, 2) p2 = Point(1, 2) p3 = Point(3, 4) print(p1 == p2) # True(逐字段比较) print(p1 == p3) # False默认按字段值比较,而不是按引用,这跟普通类不同。
四、@dataclass的参数
@dataclass( init=True, # 是否生成 __init__ repr=True, # 是否生成 __repr__ eq=True, # 是否生成 __eq__ order=False, # 是否生成比较方法(<, <=, >, >=) unsafe_hash=False, # 是否生成 __hash__ frozen=False # 是否不可变 ) class MyClass: ...| 参数 | 默认值 | 说明 |
|---|---|---|
init | True | 生成__init__ |
repr | True | 生成__repr__ |
eq | True | 生成__eq__ |
order | False | 生成<、<=、>、>= |
unsafe_hash | False | 生成__hash__ |
frozen | False | 实例不可变 |
常用组合:
# 只读数据类 @dataclass(frozen=True) class Config: host: str port: int # 可排序的数据类 @dataclass(order=True) class Student: score: int name: str五、默认值
1. 简单默认值
@dataclass class User: name: str age: int = 18 is_active: bool = True2. 可变默认值
# 错误:所有实例共享同一个列表 @dataclass class Bad: items: list = [] # 报错信息: # ValueError: mutable default <class 'list'> for field items is not allowed原因:可变对象作为默认值会导致所有实例共享同一个对象。
正确做法:用field(default_factory=...)
from dataclasses import dataclass, field @dataclass class Good: items: list = field(default_factory=list) tags: dict = field(default_factory=dict) names: set = field(default_factory=set) g1 = Good() g2 = Good() g1.items.append(1) print(g2.items) # [],g2 不受影响说明:list、dict、set等可变对象,默认值一律用field(default_factory=...)