Loading

python 标准库 dataclasses 使用指南

简单使用

dataclasses 可以用来快速的定义数据类,并能够简单明了的指明该类所具有的属性和类型,比如,要定义一个名为 Person 的类,常规的写法如下:

class Person:

    def __int__(self, id: int, first_name: str, last_name: str, eye_color: str):
        self.id = id
        self.first_name = first_name
        self.last_name = last_name
        self.eye_color = eye_color

如果使用 dataclasses ,写法则会简单很多:

from dataclasses import dataclass

@dataclass
class Person:
    id: int
    first_name: str
    last_name: str
    eye_color: str

dataclasses 将属性都作为类属性定义,不需要再写一遍参数,再写一遍实例属性绑定了,不仅写起来方便,看起来也很清晰。而且在初始化实例时,也会有对应参数的类型提示。

看起来如此简单,那么 dataclasses 还做了哪些其他的工作呢?

数据展示

试着初始化一个实例并看看样子:

>>> john = Person(1, first_name="John", last_name="Doe", eye_color="black")
>>> print(john)
Person(id=1, first_name='John', last_name='Doe', eye_color='black')

可以通过 print 输出的命令同样也很清晰的代表了实例的内容。看来 dataclasses 同时也为 Person 定义了 __str____repr__ 方法。

数据对比

如果再初始化一个实例,并与之前的对比呢?属性不同的话,期望的结果也是不相等的,试试看:

>>> bob = Person(2, first_name="Bob", last_name="Doe", eye_color="black")
>>> print(john == bob)
False

那么如果属性一致,那么期望结果也是相等的:

>>> john2 = Person(1, first_name="John", last_name="Doe", eye_color="black")
>>> print(john2 == john)
True

属性冻结

如果希望生成的实例属性不可变更,可以加入 frozen=True 参数:

@dataclass(frozen=True)
class Person:
    id: int
    first_name: str
    last_name: str
    eye_color: str

此时对实例做属性更改,则会遇到异常:

>>> john = Person(1, first_name="John", last_name="Doe", eye_color="black")
>>> john.last_name = 'Jan'
Traceback (most recent call last):
  File "...", line 20, in <module>
    john.last_name = 'Jan'
  File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'last_name'

定义初始化参数

如果有的参数,只想让它在初始化时传入,但是不要作为实例属性,可以通过 __post_init__ 方法处理,比如,现在想在 Person 的实例化时接收一个 city_id 作为所在城市的数据信息 id,但是在真正调用的时候,希望能够通过 person.city 直接读取到 city_id 所代表的内容。可以这样处理:

from dataclasses import dataclass, InitVar, field


class City(object):
    @classmethod
    def from_id(cls, id):
        return cls()


@dataclass
class Person:
    id: int
    first_name: str
    last_name: str
    eye_color: str
    city_id: InitVar[int]
    city: City = field(init=False)

    def __post_init__(self, city_id: int):
        self.city = City.from_id(city_id)

其他参数

除上述之外, dataclass 装饰器还支持很多定制化的参数,比如 kw_only 是否支持只传入关键字,order 是否支持大于、小于等比较操作,具体可参考官方文档

参考

  1. dataclasses --- 数据类 — Python 3.12.3 文档
posted @ 2024-06-05 13:28  kingron  阅读(25)  评论(0编辑  收藏  举报