python之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 指定数据类对象的排序属性。
python之DataClass的更多相关文章
- Python中dataclass库
目录 dataclass语法 一. 简介 二. 装饰器参数 三. 数据属性 1. 参数 2. 使用示例 3. 注意事项 四. 其他 1. 常用函数 2. 继承 3. 总结 dataclass语法 一. ...
- Python 3.7 将引入 dataclass 装饰器
简评:Python 3.7 将于今年夏天发布,Python 3.7 中将会有许多新东西,最激动人心的新功能之一是 dataclass 装饰器. 什么是 Data Class 大多数 Python 开发 ...
- Python 3.X简史——记录3.0之后的重要更新
Python 3.0在2008年12月3日正式发布,在之后又经历了多个小版本(3.1,3.2,3.3……),本文梳理Python 3.0之后的新特性. 其实每个版本都有大量更新,都写出来要几百页,这里 ...
- Python3.7 dataclass使用指南
本文将带你走进python3.7的新特性dataclass,通过本文你将学会dataclass的使用并避免踏入某些陷阱. dataclass简介 dataclass的使用 定义一个dataclass ...
- Python3.7 dataclass 介绍
Posted on 2018年6月28日 by laixintao 1 Comment Python3.7 加入了一个新的 module:dataclasses.可以简单的理解成“支持默认值.可以修改 ...
- Python 装饰器入门(下)
继续上次的进度:https://www.cnblogs.com/flashBoxer/p/9847521.html 正文: 装饰类 在类中有两种不通的方式使用装饰器,第一个和我们之前做过的函数非常相似 ...
- Python爬虫学习 - day1 - 爬取图片
利用Python完成简单的图片爬取 最近学习到了爬虫,瞬时觉得很高大上,想取什么就取什么,感觉要上天.这里分享一个简单的爬取汽车之家文章列表的图片教程,供大家学习. 需要的知识点储备 本次爬虫脚本依赖 ...
- python 类的使用
目录 类的继承 类的派生 类的组合 菱形继承问题 多态与多态性 dataclass的使用 类的继承 什么是继承,在生活中,子承父业,父亲和儿子就是继承的关系 在python中,父类和子类(派生类),父 ...
- 整理了8个Python中既冷门又实用的技巧
1.print 打印带有颜色的信息 大家知道 Python 中的信息打印函数 print,一般我们会使用它打印一些东西,作为一个简单调试. 但是你知道么,这个 Print 打印出来的字体颜色是可以设置 ...
- python数据类
前言 之前有写过一篇python元类的笔记,元类主要作用就是在要创建的类中使用参数metaclass=YourMetaclass调用自定义的元类,这样就可以为所有调用了这个元类的类添加相同的属性了. ...
随机推荐
- 游戏AI行为决策——GOAP(目标导向型行动规划)
游戏AI行为决策--GOAP(附代码与项目) 新的一年即将到来,感觉还剩一种常见的游戏AI决策方法不讲的话,有些过意不去.就在这年的尾巴与大家一起交流下「目标导向型行为规划(GOAP)」吧! 另外,我 ...
- 如何使用 Redis 实现后台房间的数据管理?
摘要:利用 Redis 实现房间业务管理的实践与思考. 文|即构业务后台开发团队 在一些互动场景中,比如语音聊天室.电商直播等,成员控制.连麦.献花.发弹幕等互动功能,通常要求后台服务器能够储 ...
- Angular Material 18+ 高级教程 – Get Started
前言 本编是 Angular Material 教程的开篇,我先介绍一下这个教程. 首先,Angular Material 教程不会像 Angular 教程那么注重原理,也很少会逛源码. 所以,如果你 ...
- CSS & JS Effect – Styling Input Radio
原生 Radio 的 Limitation <input type="radio" style="width: 25px; height: 25px; cursor ...
- Angular 学习笔记 (Angular 12 get started)
Angular 12 视乎比以往更稳定了. 这里记入一般的 get started 结构和做法. 第 1 步, 创建项目. ng new project --create-application=fa ...
- QT与JavaScript之QT6应用程序与JavaScript脚本集成开发:C++应用程序能与JavaScript实现相互调用吗?
简介 QT6框架中提供了JavaScript引擎类型QJSEngine ,可用于实现 C++应用程序和JavaScript代码之间的相互调用. 目录 什么是 ECMAScript ? JavaScri ...
- Python 潮流周刊#70:微软 Excel 中的 Python 正式发布!(摘要)
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- 揭秘!尤雨溪成立的VoidZero如何改变前端世界
前言 Vue和Vite之父尤雨溪宣布成立公司 VoidZero,目前已经融资3200万.这篇文章欧阳将带你了解VoidZero是如何改变javascript的世界! 关注公众号:[前端欧阳],给自己一 ...
- 随心所动,厂商的CPU核管理策略介绍
一.引文 随着CPU架构的发展,工艺的升级,带来性能提升,能效的提升(同性能下).但是由于极限性能的增加,也带来了peak功耗的增加(大部分情况下,能效比的提升无法抵消这部分),CPU功耗优化一直是广 ...
- Android Systrace 基础知识 -- Systrace 简介
1. 正文 Systrace 是 Android4.1 中新增的性能数据采样和分析工具.它可帮助开发者收集 Android 关键子系统(如 SurfaceFlinger/SystemServer/Ke ...