Python dataclasses 数据类模块详细教程说明
dataclasses
是 Python 3.7+ 引入的一个模块,它提供了一个装饰器和一些函数,用于自动为类添加特殊方法(如 __init__()
, __repr__()
, __eq__()
等),从而简化类的定义。它的主要目的是减少编写样板代码的工作量,特别是在创建主要用来存储数据的类时。
1.基本用法
最简单的 dataclass
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
这个简单的定义会自动生成以下方法:
__init__(self, x: float, y: float)
__repr__(self)
__eq__(self, other)
使用示例:
p = Point(1.5, 2.5) # 不需要手动编写 __init__
print(p) # 输出: Point(x=1.5, y=2.5)
p2 = Point(1.5, 2.5)
print(p == p2) # 输出: True
dataclass 装饰器参数
@dataclass
装饰器接受多个参数来定制生成的方法:
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class Example:
# 类定义
常用参数:
init
: 是否生成__init__
方法(默认为 True)repr
: 是否生成__repr__
方法(默认为 True)eq
: 是否生成__eq__
方法(默认为 True)order
: 是否生成比较方法(__lt__
,__le__
,__gt__
,__ge__
,默认为 False)frozen
: 设为 True 时,实例创建后字段不可修改(默认为 False)
2.字段选项
默认值
@dataclass
class Point:
x: float = 0.0
y: float = 0.0
使用 field() 进行更精细控制
from dataclasses import dataclass, field
@dataclass
class C:
x: int
y: int = field(repr=False) # y 不会出现在 repr 输出中
z: int = field(default=10, compare=False) # z 不参与比较
w: list = field(default_factory=list) # 默认值为空列表
field()
常用参数:
default
: 默认值default_factory
: 一个无参函数,用于生成可变默认值init
: 是否包含在__init__
参数中(默认为 True)repr
: 是否包含在__repr__
输出中(默认为 True)compare
: 是否包含在比较方法中(默认为 True)hash
: 是否包含在哈希计算中(默认为与 compare 相同)
3.高级特性
不可变 dataclass
@dataclass(frozen=True)
class ImmutablePoint:
x: float
y: float
尝试修改字段会引发 FrozenInstanceError
:
p = ImmutablePoint(1.0, 2.0)
p.x = 3.0 # 抛出 FrozenInstanceError
排序
@dataclass(order=True)
class OrderedPoint:
x: float
y: float
这会生成 __lt__()
, __le__()
, __gt__()
, __ge__()
方法,比较时会按字段定义的顺序比较字段值。
继承
dataclass 支持继承:
@dataclass
class Person:
name: str
age: int
@dataclass
class Employee(Person):
emp_id: str
salary: float
注意:基类必须是 dataclass 或具有兼容的 __init__
方法。
后初始化处理
使用 __post_init__
方法可以在 __init__
之后执行额外操作:
@dataclass
class Rectangle:
width: float
height: float
area: float = field(init=False) # 不在 __init__ 中初始化
def __post_init__(self):
self.area = self.width * self.height
4.应用示例
配置类
@dataclass
class AppConfig:
host: str = 'localhost'
port: int = 8080
debug: bool = False
database_url: str = 'sqlite:///:memory:'
数据记录
@dataclass
class InventoryItem:
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
嵌套 dataclass
@dataclass
class Address:
street: str
city: str
zip_code: str
@dataclass
class User:
name: str
email: str
address: Address
5.对比普通类
传统写法
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __eq__(self, other):
if not isinstance(other, Point):
return False
return self.x == other.x and self.y == other.y
dataclass 写法
@dataclass
class Point:
x: float
y: float
6.注意事项
dataclass 生成的代码与手写代码性能相当。对于性能关键代码,可以考虑:
- 使用
@dataclass(slots=True)
(Python 3.10+) 来减少内存使用 - 对于大量实例,考虑使用
frozen=True
使实例可哈希,便于作为字典键
总结
dataclasses
模块的主要优点:
- 减少样板代码
- 提高代码可读性
- 内置有用的功能(如比较、字符串表示)
- 与类型提示完美配合
- 灵活的定制选项
它特别适合用于:
- 配置对象
- 数据传输对象
- 记录结构
- 任何主要目的是存储数据的类
对于更复杂的需求,可以考虑 attrs
库(dataclasses
的灵感来源),它提供了更多功能。