首页 > 编程语言 >python之DataClass

python之DataClass

时间:2023-12-18 09:59:20浏览次数:36  
标签:__ name python age Person init dataclass DataClass

Python 在版本 3.7 (PEP 557) 中引入了dataclass。dataclass允许你用更少的代码和更多的开箱即用功能来定义类。

下面定义了一个具有两个实例属性 name 和 age 的常规 Person 类:

 

class Person:

   def __init__(self, name, age):

       self.name = name

       self.age = age

 

这个 Person 类具有初始化 name 和 age 属性的__init__ 方法。

如果你想要一个 Person 对象的字符串表示,你需要实现__str__ 或 __repr__方法。另外,如果要通过属性比较 Person 类的两个实例,则需要实现__eq__方法。

但是,如果你使用数据类,你将拥有所有这些功能(甚至更多),而无需实现这些 dunder 方法。

要使 Person 类成为数据类,请执行以下步骤:

首先,从 dataclasses 模块导入 dataclass 装饰器:

 

from dataclasses import dataclass

其次,用 dataclass 装饰器装饰 Person 类并声明属性:

 

@dataclass
class Person:
   name: str
   age: int

 

在这个例子中,Person 类有两个属性 name 类型为 str 和 age 类型为 int, 这样@dataclass 装饰器隐式创建__init__方法,如下所示:

 

def __init__(name: str, age: int)

 

请注意,类中声明的属性的顺序将决定__init__ 方法中参数的顺序。

你可以创建 Person 的对象:

 

p1 = Person('John', 25)

 

当打印出 Person 的对象时,你会得到一个可读的格式:

 

print(p1)

输出:

 

Person(name='John', age=25)

此外,如果你比较两个具有相同属性值的 Person 对象,它将返回 True。例如:

 

p1 = Person('John', 25)
p2 = Person('John', 25)
print(p1 == p2)

 

输出

True

下面讨论数据类提供的其他功能。

默认值

使用常规类时,你可以定义属性的默认值。例如,以下 Person 类的 iq 参数的默认值为 100。

 

class Person:
    def __init__(self, name, age, iq=100):
        self.name = name
        self.age = age
        self.iq = iq

 

要为数据类中的属性定义默认值,请将其分配给属性,如下所示:

 

from dataclasses import dataclass
@dataclass
class Person:
    name: str
    age: int
    iq: int = 100
print(Person('John Doe', 25))

 

与参数规则一样,具有默认值的属性必须出现在没有默认值的属性之后。因此,以下代码将不起作用:

 

from dataclasses import dataclass
@dataclass
class Person:
    iq: int = 100
    name: str
    age: int

 

转换为元组或字典

dataclasses 模块具有 astuple() 和 asdict() 函数,它们将数据类的实例转换为元组和字典。例如:

 

from dataclasses import dataclass, astuple, asdict
@dataclass
class Person:
    name: str
    age: int
    iq: int = 100
p = Person('John Doe', 25)
print(astuple(p))
print(asdict(p))

 

输出:

('John Doe', 25, 100)
{'name': 'John Doe', 'age': 25, 'iq': 100}

 

创建不可变对象

要从数据类创建只读对象,可以将数据类装饰器的冻结参数设置为 True。例如:

 

from dataclasses import dataclass, astuple, asdict
@dataclass(frozen=True)
class Person:
    name: str
    age: int
    iq: int = 100

 

如果你在创建对象后尝试更改其属性,则会收到错误消息。例如:

 

p = Person('Jane Doe', 25)
p.iq = 120

 

错误信息:

 

dataclasses.FrozenInstanceError: cannot assign to field 'iq'

自定义属性行为

如果不想在 __init__ 方法中初始化属性,可以使用 dataclasses 模块中的 field() 函数。

以下示例定义了使用 __init__方法初始化的 can_vote 属性:

 

from dataclasses import dataclass, field
class Person:
    name: str
    age: int
    iq: int = 100
    can_vote: bool = field(init=False)

 

field() 函数有多个有趣的参数,例如 repr、hash、compare 和 metadata。

如果要初始化一个依赖于另一个属性值的属性,可以使用__post_init__ 方法。顾名思义,Python 在 __init__方法之后调用 __post_init__ 方法。

下面使用__post_init__ 方法根据 age 属性初始化 can_vote 属性:

 

from dataclasses import dataclass, field
@dataclass
class Person:
    name: str
    age: int
    iq: int = 100
    can_vote: bool = field(init=False)
    def __post_init__(self):
        print('called __post_init__ method')
        self.can_vote = 18 <= self.age <= 70
p = Person('Jane Doe', 25)
print(p)

输出:

 

called the __post_init__ method
Person(name='Jane Doe', age=25, iq=100, can_vote=True)

 

对对象进行排序

默认情况下,数据类实现 __eq__方法。

要允许不同类型的比较,如__lt__、__lte__、__gt__、__gte__,你可以将 @dataclass 装饰器的 order 参数设置为 True:

 

@dataclass(order=True)

 

通过这样做,数据类将按每个字段对对象进行排序,直到找到不相等的值。

在实践中,你经常希望通过特定属性而不是所有属性来比较对象。为此,你需要定义一个名为 sort_index 的字段并将其值设置为要排序的属性。

例如,假设你有一个 Person 对象列表,并希望按年龄对它们进行排序:

 

members = [
    Person('John', 25),
    Person('Bob', 35),
    Person('Alice', 30)
]

 

 

因为,需要:

  • 首先,将 order=True 参数传递给 @dataclass 装饰器。
  • 其次,定义 sort_index 属性并将其 init 参数设置为 False。
  •  第三,在 __post_init__方法中将 sort_index 设置为 age 属性,以按年龄对 Person 的对象进行排序。

 

from dataclasses import dataclass, field
@dataclass(order=True)
class Person:
    sort_index: int = field(init=False, repr=False)
    name: str
    age: int
    iq: int = 100
    can_vote: bool = field(init=False)
    def __post_init__(self):
        self.can_vote = 18 <= self.age <= 70
        # sort by age
        self.sort_index = self.age
members = [
    Person(name='John', age=25),
    Person(name='Bob', age=35),
    Person(name='Alice', age=30)
]
sorted_members = sorted(members)
for member in sorted_members:
    print(f'{member.name}(age={member.age})')

 

输出:

John(age=25)
Alice(age=30)
Bob(age=35)

总结

  • 使用 dataclasses 模块中的 @dataclass 装饰器使类成为数据类。数据类对象默认实现__eq__和__str__。
  • 使用 astuple() 和 asdict() 函数将数据类的对象转换为元组和字典。
  • 使用 freeze=True 定义一个对象不可变的类。
  • 使用 __post_init__ 方法初始化依赖于其他属性的属性。
  • 使用 sort_index 指定数据类对象的排序属性。

标签:__,name,python,age,Person,init,dataclass,DataClass
From: https://www.cnblogs.com/xingxia/p/python_dataclass.html

相关文章

  • python迭代器理解
    目录什么是迭代器?为什么要有迭代?迭代器的优缺点什么是可迭代对象?什么是迭代器对象呢?什么是迭代器?在学习for循环的时候,听到了一个词叫可迭代对象。那什么是可迭代对象?了解后又知道了迭代,可迭代,迭代器这些名词,那这些到底是什么意思呢?我们先知道为什么for循环不像whlie循环一样,使......
  • Machine Learning in Python
    MetricFormulaInterpretationAccuracy$\frac{TP+TN}{TP+TN+FP+FN}$OverallperformanceofmodelPrecision$\frac{TP}{TP+FN}$HowaccuratethepositivepredictionsareRecallSensitivity$\frac{TP}{TP+FP}$Coverageofactualpositivesampl......
  • python网站创建011:函数、序列化
    经典函数:JS经典函数定义function函数名(a1,a2){vara3=a1+a2returna3}varres=函数名(11,22)console.log(res) 那如何在浏览器中查看打印结果呢?  匿名函数:没名字的函数,如果只有一个地方用到,则直接使用......
  • 系统聚类思想及其Python实现
    系统聚类是一种将对象或数据按照其相似性进行分组的方法。与传统聚类方法不同,系统聚类通过构建一颗层次树(或称为树状图或谱系图)来展现数据的层次结构。在系统聚类中,数据点最初被视为单独的簇,然后通过逐步合并或分裂,形成一个层次结构的聚类结果。这种层次结构可用于分析数据的不同......
  • Python——作图
    Python——作图百分比堆积柱状图importmatplotlib.pyplotaspltimportnumpyasnp#定义数据categories=['CatA','CatB','CatC']values1=[20,30,15]values2=[10,25,20]values3=[5,10,15]#将数据转化为相对百分比total=np.array(v......
  • Python: Random
     #encoding:utf-8#版权所有2023涂聚文有限公司#许可信息查看:#描述:https://docs.python.org/3/library/string.html#Author:geovindu,GeovinDu涂聚文.#IDE:PyCharm2023.1python3.11#Datetime:2023/12/1718:16#User:geovindu#P......
  • python常用内置模块(持续更新中)
    random模块相关方法需要掌握的,未提及的建议自行了解importrandom大于0且小于1之间的小数(不含1)random.random()#0.38916016381720087指定区间指定start到end(不含end)之间的随机小数random.uniform(0,10)#8.080921224222864指定区间指定start到end(含end)之......
  • Python模块与包
    【一】模块的介绍【1】什么是模块在Python中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块可以引用模块中已经写好的功能。如果把开发程序比喻成制造一台电脑编写模块就像是在制造电脑的零部件准备好零部件后,剩下的工作就是按照逻辑把它们组装到一起。将......
  • Python迭代器和生成器
    【一】迭代器介绍迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代whileTrue:msg=input(">>:").strip()......
  • python 浮点数 round 舍一法 向零取整 df 数组 Series 三种数据类型实现
    介绍:python的round函数,默认进行四舍五入,我需要将3.45保留一位小数,3.4 一、一般格式使用Python的内置函数 math.floor() 来向下取整到指定的小数位数。例如,如果你想保留小数点后一位并向下取整,可以这样做:importmathnum=3.45rounded_num=math.floor(num*10)/......