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调用自定义的元类,这样就可以为所有调用了这个元类的类添加相同的属性了. ...
随机推荐
- 【YashanDB知识库】存储过程报错snapshot too old
问题描述 20231127上午客户反馈绩效系统20231125.20231126出现2次YAS-02020 snapshot too old的问题,测试也有类似问题. 该过程是客户新增的存储过程,目的 ...
- (零) React Native 项目开发拾遗
一位离职的前端同事,最近接了个 React Native 的活儿,遇到许多搞不定的问题,于是找到我帮忙"补课"(没有系统的学习 React Native,也不具备原生 Androi ...
- CSS 实现滑动整个元素
其实没什么难点,主要就是两个CSS属性 scroll-snap-type 这个是作用在包裹容器身上的. scroll-snap-align 这个是作用在被包裹容器身上的. 效果如下图所示: 代码如下: ...
- hexo使用小技巧
1.在博客中加入图片 使用语法 {% asset_img 1.jpg %} 这样hexo会自动渲染1.jpg.,然后1.jpg的位置需要放在同文件名的文件夹中,比如这篇博客叫hexo使用小技巧,那么这 ...
- ASP.NET Core C# 反射 & 表达式树 (第四篇)
前言 上一篇说完了动态创建表达式树, 这篇来说一说解析表达式树. 我之所以会用到是因为最近开始大量使用 trigger 来维护冗余. 但 trigger 本身并不好维护 (EF Core 也不支持), ...
- Session——基本使用
Session Session 原理 Session 使用细节
- 智和信通搭建高可靠、真稳定IT运维平台,助力能源行业高效生产
在能源企业信息化高度发展的背景下,北京智和信通有限公司推出全栈式运维管控平台--"智和网管平台",助力能源企业搭建高可靠.真稳定的IT运维平台,实现高效稳定生产. 信息化飞速发展, ...
- USB gadget configfs
概述 USB Linux Gadget是一种具有UDC (USB设备控制器)的设备,可以连接到USB主机,以扩展其附加功能,如串口或大容量存储能力. 一个gadget被它的主机视为一组配置,每个配置都 ...
- yaml.load与yaml.dump的用法
import yaml #向yaml文件中写 with open("E:\个人\ rename.yaml", 'w') as f: project = {'在远方':"1 ...
- Excel读写之xlrd模块
1.1.xlrd模块介绍 xlrd:用于读取Excle数据文件将返回的数据对象放到内存中,然后查询数据文件对象的相关信息. xlwt:用于在内存中生成新的数据文件对象,处理完成后写入到Excel数据文 ...