数据类适用于Python3.7以上版本。它不仅可以用作数据容器,还可以编写样板代码来简化创建类的过程。创建第一个数据类创建一个表示三维坐标系中的点的数据类。@dataclass装饰器用于创建数据类。x、y和z是数据类中的字段。请注意,类型注释用于指定字段的数据类型,但类型注释不是静态类型声明,这意味着除了int之外的任何数据类型仍然可以为x、y或z字段传递。fromdataclassesimportdataclass@dataclassclassCoordinate:x:inty:intz:int默认情况下,数据类带有init、repr和eq方法,因此我们不必自己实现它们。但是如果init、repr、eq没有在Coordinate类中实现,有了data类,我们仍然可以使用这些方法,非常省时。fromdataclassesimportdataclass@dataclassclassCoordinate:x:inty:intz:inta=Coordinate(4,5,3)print(a)#output:Coordinate(x=4,y=5,z=3)fieldencoder的默认值可以字段分配默认值。数据类中的pi字段赋值如下:fromdataclassesimportdataclass@dataclassclassCircleArea:r:intpi:float=3.14@propertydefaarea(self):returnsself.pi*(self.r**2)a=CircleArea(2)print(repr(a))#output:CircleArea(r=2,pi=3.14)print(a.area)#output:12.56自定义字段和数据类设置dataclass装饰器或字段函数的参数来自定义字段和数据类。自定义过程将以实例说明,字段和数据类的所有参数将在文末给出。数据类是可变的还是不可变的?默认情况下,数据类是可变的,这意味着可以为字段赋值。但是我们可以通过将frozen参数设置为TrueMutable示例使其不可变:fromdataclassesimportdataclass@dataclassclassCircleArea:r:intpi:float=3.14@propertydefaarea(self):returnsself.pi*(self.r**2)a=CircleArea(2)a.r=5print(repr(a))#output:CircleArea(r=5,pi=3.14)print(a.area)#output:78.5不可变例子:设置frozen为True,将不再为字段赋值.异常输出可以在下面的示例中看到。fromdataclassesimportdataclass@dataclass(frozen=True)classCircleArea:r:intpi:float=3.14@propertydefarea(self):returnself.pi*(self.r**2)a=CircleArea(2)a.r=5#Exceptionoccurred:dataclasses。FrozenInstanceError:#cannotassigntofield'r'Comparingdataclasses假设你想创建一个表示Vector的数据类并比较它,你会怎么做?当然你需要使用lt或者gt之类的方法。默认情况下,数据类的顺序参数为False。将其设置为True会自动为数据类生成lt、le、gt和ge方法。因此,对象可以按顺序进行比较,就好像它们是其字段的元组一样。研究以下示例:将order设置为True将比较v2和v1。这里有个逻辑比较问题。当v2>v1时,它比较这两个向量,例如(8,15)>(7,20)。因此,v2>v1的输出将为True。回想一下,元组比较是按顺序执行的。先比较8和7,结果为True,再比较结果为True。如果相等,比较15>20,结果为False:fromdataclassesimportdataclass,field@dataclass(order=True)classVector:x:inty:intv1=Vector(8,15)v2=Vector(7,20)print(v2>v1)显然这种比较没有任何意义。作者本来是想按大小比较向量。但是问题是在创建每个实例的时候无法计算出Vector的大小。在这种情况下,field函数和post_init方法就更有用了。场函数可以自定义量级场。post_init方法将确定初始化后向量的大小。您还可以使用数据类中的场函数来自定义量级场。通过将init设置为False,init方法中的magnitude参数基本上是不必要的。因为初始化后使用post_init方法确定其值:fromdataclassesimportdataclass,field@dataclass(order=True)classVector:magnitude:float=field(init=False)x:inty:intdef__post_init__(self):self.magnitude=(self.x**2+self.y**2)**0.5v1=Vector(9,12)print(v1)#output:Vector(magnitude=15.0,x=9,y=12)v2=Vector(8,15)print(v2)#output:Vector(magnitude=17.0,x=8,y=15)print(v2>v1)#output:True将数据类转换为字典或元组从元组或字典中获取数据的属性该类只需要从数据类导入asdict和astuple函数:fromdataclassesimportdataclass,asdict,astuple@dataclassclassVector:x:inty:intz:intv=Vector(4,5,7)print(asdict(v))#output:{'x':4,'y':5,'z':7}print(astuple(v))#output:(4,5,7)继承可以像Python中的普通类一样对数据类进行子类分类:fromdataclassesimportdataclass@dataclassclassEmployee:name:strlang:str@dataclassclassDeveloper(Employee):salary:intHalil=Developer('Halil','Python',5000)print(Halil)#Output:Developer(name='Halil',lang='Python',salary=5000)在使用继承的时候,有一点经常被忽略:默认情况下,当lang字段设置为Python时,一个必须为lang字段后的字段提供默认值:fromdataclassesimportdataclass@dataclassclassEmployee:name:strlang:str='Python'@dataclassclassDeveloper(Employee):salary:intHalil=Developer('Halil','Python',5000)#Output:TypeError:non-defaultargument'salary'followsdefaultargument是由于init方法参数应该在参数之后没有默认值:def__init__(name:str,lang:str='Python',salary:int):...通过设置默认值修复sanlary字段:fromdataclassesimportdataclass@dataclassclassEmployee:name:strlang:str='Python'@dataclassclassDeveloper(Employee):salary:int=0Halil=Developer('Halil','Python',5000)print(Halil)#output:Developer(name='Halil',lang='BenefitsofPython',salary=5000)slots默认情况下,属性存储在字典中。使用插槽可以更快地访问属性并占用更少的内存。fromdataclassesimportdataclass@dataclassclassEmployee:name:strlang:strHalil=Employee('Halil','Python')print(Halil.__dict__)#name':'Halil','lang':'Python'}槽内存占用更小,访问属性快点。fromdataclassesimportdataclass@dataclassclassEmployee:__slots__=('name','lang')name:strlang:strHalil=Employee('Halil','Python')数据类参数我们只是将数据类装饰器中的一些参数更改为自定义数据类。以下是参数列表:nit:如果为True,则在数据类中生成init方法。(默认为True)repr:如果为True,则在数据类中生成一个repr方法。(默认为True)eq:如果为True,则在数据类中生成eq方法。(默认为True)order:如果为True,则在数据类中生成lt、le、gt和ge方法。(默认为False)unsafe_hash:如果为True,在数据类中生成一个散列方法。(默认为False)frozen:如果为True,则该字段不能被赋值。(默认为False。)请注意,如果order为True,则eq也必须为True,否则将引发ValueError异常。field参数init:如果为True,则该字段包含在生成的init方法中。(默认为True)repr:如果为True,则此字段包含在生成的repr方法中。(默认为True)compare:如果为True,则此字段包含在生成的比较和相等方法中。(默认True)hash:如果为True,则此字段包含在生成的哈希方法中。(默认无)默认值:如果提供,这是该字段的默认值。default_factory:当字段需要默认值时将调用此参数,此时参数必须是零阶可调用参数对象。metadata:可以是map也可以是空的,如果是空的,会被当作空字典。以上就是对Python中数据类的简单介绍,你掌握了吗?
