数据类
自3.7版本开始,Python引入了一个新的功能:数据类(dataclass)。根据PEP-557的定义,数据类是一个带有默认值的可变命名元组。可以认为数据类就是一个类,其中的属性都是公有的,属性都带有默认值并且可以修改,这个类中还可以包含与这些属性相关的方法。
声明一个数据类需要引入dataclasses
模块中的dataclass
修饰器。以下给出一个简单的数据类示例。
from dataclasses import dataclass, field
@dataclass
def Book:
name = ""
isbn = ""
price = 0.0
authors = field(default_factory=list)
数据类在定义后会自动产生一个为所有属性赋值的构造函数,并且会自动建立__repr__()
和__eq__()
两个方法。数据类中的属性可以不带有默认值,但是需要注意的是不带默认值的属性要写在带有默认值的属性前面,这与函数参数的书写顺序要求是一致的。
修饰器dataclass
可以接受一些参数来自定义数据类的建立,主要的参数有以下这些,全都都只接受布尔类型值。
init
,指示是否生成构造函数,如果需要自己定义构造函数则应设置为False
。repr
,指示是否生成__repr__()
方法。eq
,指示是否生成__eq__()
方法。order
,指示是否生成__lt__()
、__gt__()
、__le__()
、__ge__()
等用于比较的方法。unsafe_hash
,根据eq
和frozen
的值来决定是否生成__hash__
。frozen
,设置为True
的时候实例对象将是不可变的。
数据类通过dataclass
修饰器自动生成的构造函数默认会调用名为__post_init__()
的方法,如果使用了默认生成的构造函数,那么一些追加的构造操作可以在__post_init__()
方法中书写。
数据类支持继承,dataclass
修饰器会检查数据类的所有基类,会将其中出现的其他数据类按顺序添加进当前的数据类中,如果子类的属性与基类的属性重名,则子类的属性会覆盖掉基类的同名属性。
数据类中的每个属性都会在dataclass
修饰器的作用下自动转化为dataclasses.Field
对象。通常这个自动转换的过程是无需干预的,但是有的时候则需要定制这个转换过程。我们可以通过dataclasses.field()
函数来定义一个属性,并声明它的特性。
正如前面示例中的authors
属性,这是一个列表,如果直接使用list()
或者[]
来定义,则会在数据类实例创建的时候仅复制列表的引用,这会造成不必要的混乱。所以使用field()
函数来定义这个属性的具体特性。dataclasses.field()
函数可以接受以下参数来定制dataclasses.Field
对象。
default
,设置属性的默认值。default_factory
,控制如何产生默认值,接受一个callable
类型值。repr
,是否包含到默认的__repr__()
方法输出中。hash
,是否参与到生成__hash__
中。init
,是否参与到构造函数中。compare
,是否参与实例比较方法。metadata
,使用字典类型值设定属性的元数据,用于第三方扩展使用。
除此之外,dataclasses
中还提供了一些常用的工具函数,其功能如下。
asdict()
,将数据类实例转换为一个字典类型实例。astuple()
,将数据类实例转换为一个元组。