跳到主要内容

dataclasses

问题

@dataclass 装饰器怎么用?和 Pydantic 有什么区别?

答案

基础用法

from dataclasses import dataclass, field

@dataclass
class User:
name: str
age: int
email: str = "" # 默认值
tags: list[str] = field(default_factory=list) # 可变默认值

def __post_init__(self):
"""初始化后的处理"""
self.name = self.name.strip()

user = User("Alice", 30)
print(user) # User(name='Alice', age=30, email='', tags=[])
print(user == User("Alice", 30)) # True(自动生成 __eq__)

高级选项

@dataclass(frozen=True)      # 不可变(生成 __hash__)
class Point:
x: float
y: float

@dataclass(slots=True) # 3.10+,使用 __slots__ 节省内存
class Config:
host: str
port: int

@dataclass(order=True) # 自动生成比较方法
class Version:
major: int
minor: int
patch: int

dataclass vs Pydantic vs namedtuple

特性dataclassPydanticnamedtuple
运行时验证
可变性默认可变默认不可变(v2)不可变
序列化需手动内置 .model_dump()_asdict()
性能最快较快(v2 Rust核心)最快
适用场景内部数据结构API 输入/输出验证简单不可变记录

常见面试问题

Q1: 为什么不用 field(default=[]) 而要用 field(default_factory=list)

答案

与函数默认参数陷阱相同:可变默认值会被所有实例共享。default_factory 确保每次创建实例时调用 list() 生成新列表。

相关链接