首页 Python 学习笔记 - dataclass
文章
取消

Python 学习笔记 - dataclass

dataclass有点像实体类的概念。通过装饰器@dataclass修饰一个类,将其转化为一个数据类。

1
2
3
4
@dataclass
class Student:
    name: str
    age: int

使用dataclass修饰后,自动实现__init__、__repr__、__eq__、__hash__等方法。

如下图例子,在定义了类属性后,自动定义对象实例属性,并根据名字和顺序编写__init__方法,并且eq方法也会自动按照对比成员属性值来判断是否相等来实现。由于是数据类,所以eq方法的实现是基于成员属性值的比较,而不是基于对象实例的比较,如果想要基于实例的话,可以设置一个id字段。

alt text

缺省值

对象成员属性可以直接定义缺省值,在构造的时候不带age参数,也会默认使用缺省值20。

1
2
3
4
@dataclass
class Student:
    name: str
    age: int = 20

alt text

不可变对象

通过给@dataclass装饰器添加frozen=True参数,可以指定类为不可变对象类。

1
2
3
4
5
6
7
@dataclass(frozen=True)
class Student:
    name: str
    age: int

student = Student("C9xx", 20)
student.age = 21 # 会产生异常

使用field定义属性行为

field可以指定成员属性在dataclass的特征,例如特定构造函数,是否参与eq方法的比较,hash方法的计算,对象打印是否打印该属性等等。

alt text

alt text

## __post_init__

__post_init__方法可以在对象实例化后,对对象实例进行初始化操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@dataclass
class Student:
    name: str
    age: int
    independent: bool = field(default=False, init=False, repr=False)

    def __post_init__(self):
        self.independent = self.age >= 19

student = Student("C9xx", 20)
print(student.independent) # True

student = Student("C9xx", 18)
print(student.independent) # False

排序

通过指定order=True参数,可以指定类为可排序对象类。

1
2
3
4
@dataclass(order=True)
class Student:
    name: str
    age: int

指定可排序之后,按照首个成员属性的值进行排序,当第一个属性相同,顺延用第二个属性排序。 也可以使用field指定排序的键,通过post init方法来给排序键赋值。

1
2
3
4
5
6
7
8
@dataclass(order=True)
class Student:
    sorted_key: str = field(init=False, repr=False)
    name: str
    age: int

    def __post_init__(self):
        self.sorted_key = self.age

但其实更方便的排序方式是使用sort函数的key参数,指定排序的键,这就与order参数无关了。

1
2
3
import operator

students.sort(key=operator.attrgetter("age"))

结语

pydantic的BaseModel感觉和dataclass也差不太多,而且好像BaseModel用得更多一些。

本文由作者按照 CC BY 4.0 进行授权