ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Python 装饰器:@dataclass(一)

Python 装饰器:@dataclass(一)

一、@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 2
2.__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: ...
参数默认值说明
initTrue生成__init__
reprTrue生成__repr__
eqTrue生成__eq__
orderFalse生成<、<=、>、>=
unsafe_hashFalse生成__hash__
frozenFalse实例不可变

常用组合:

# 只读数据类 @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 = True
2. 可变默认值
# 错误:所有实例共享同一个列表 @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=...)

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进