dataclass是从Python3.7版本开始,作为标准库中的模块被引入。
随着Python版本的不断更新,dataclass也逐步发展和完善,为Python开发者提供了更加便捷的数据类创建和管理方式。

dataclass的主要功能在于帮助我们简化数据类的定义过程。
本文总结了几个我平时使用较多dataclass技巧。

1. 传统的类定义方式

首先,从平时量化分析的场景中简化一个关于 币交易 的类用来演示。
简化之后,这里只保留5个字段,分别是交易ID交易对价格是否成功参与交易的地址列表

class CoinTrans:
def __init__(
self,
id: str,
symbol: str,
price: float,
is_success: bool,
addrs: list,
) -> None:
self.id = id
self.symbol = symbol
self.price = price
self.addrs = addrs
self.is_success = is_success

Python传统定义类的方式,如上通过__init__函数来初始化对象的各个属性。

通过这个类构造对象并打印:

if __name__ == "__main__":
coin_trans = CoinTrans("id01", "BTC/USDT", "71000", True, ["0x1111", "0x2222"])
print(coin_trans)

运行结果:

<__main__.CoinTrans object at 0x0000022A891FADD0>

这里只是打印出对象的地址,并没有按照我们期望的那样打印对象各个属性的值。

传统的类中,我们如果希望打印出可读的结果,需要自己去实现__str__函数。

# 在上面的 CoinTrans 类中添加下面的方法
def __str__(self) -> str:
return f"交易信息:{self.id}, {self.symbol}, {self.price}, {self.addrs}, {self.is_success}"

再次运行,结果如下:

交易信息:id01, BTC/USDT, 71000, ['0x1111', '0x2222'], True

2. dataclass装饰器定义类

下面看看使用dataclass装饰器来定义上面同样的类有多简单。

from dataclasses import dataclass

@dataclass
class CoinTrans:
id: str
symbol: str
price: float
is_success: bool
addrs: list

再次运行:

if __name__ == "__main__":
coin_trans = CoinTrans("id01", "BTC/USDT", "71000", True, ["0x1111", "0x2222"])
print(coin_trans)

得到如下结果:

CoinTrans(id='id01', symbol='BTC/USDT', price='71000', is_success=True, addrs=['0x1111', '0x2222'])

不需要__init__,也不需要__str__,只要通过 @dataclass装饰之后,就可以打印出对象的具体内容。

2.1. 默认值

dataclass装饰器的方式来定义类,设置默认值很简单,直接在定义属性时就可以设置。

@dataclass
class CoinTrans:
id: str = "id01"
symbol: str = "BTC/USDT"
price: float = "71000.8"
is_success: bool = True
addrs: list[str] = ["0x1111", "0x2222"] if __name__ == "__main__":
coin_trans = CoinTrans()
print(coin_trans)

运行之后发现,在addrs属性那行会报错:

ValueError: mutable default <class 'list'> for field addrs is not allowed: use default_factory

大概的意思就是,list作为一种可变的类型(引用类型,会有被其他对象意外修改的风险),不能直接作为默认值,需要用工厂方法来产生默认值。
其他字符串,数值,布尔类型的数据则没有这个问题。

我们只要定义个函数来产生此默认值即可。

def gen_list():
return ["0x1111", "0x2222"] @dataclass
class CoinTrans:
id: str = "id01"
symbol: str = "BTC/USDT"
price: float = "71000.8"
is_success: bool = True
addrs: list[str] = field(default_factory=gen_list) if __name__ == "__main__":
coin_trans = CoinTrans()
print(coin_trans)

再次运行,可以正常执行:

CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8', is_success=True, addrs=['0x1111', '0x2222']

2.2. 隐藏敏感信息

我们打印对象信息的时候,有时执行打印其中几个属性的信息,涉及敏感信息的属性不希望打印出来。
比如,上面的对象,如果不想打印出is_successaddrs的信息,可以设置repr=False

@dataclass
class CoinTrans:
id: str = "id01"
symbol: str = "BTC/USDT"
price: float = "71000.8"
is_success: bool = field(default=True, repr=False)
addrs: list[str] = field(default_factory=gen_list, repr=False)

再次运行后显示:

CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8')

2.3. 只读对象

数据分析时,大部分下情况下,原始数据读取之后是不能修改的。
这种情况下,我们可以用dataclassfrozen属性来设置数据类只读,防止不小心篡改了数据。

未设置frozen属性之前,可以随意修改对象的属性,比如:

if __name__ == "__main__":
coin_trans = CoinTrans()
print(f"修改前: {coin_trans}")
coin_trans.symbol = "ETH/USDT"
print(f"修改后: {coin_trans}")

运行结果:

修改前: CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8')
修改后: CoinTrans(id='id01', symbol='ETH/USDT', price='71000.8')

设置frozen属性之后,看看修改属性值会怎么样:

@dataclass(frozen=True)
class CoinTrans:
id: str = "id01"
#... 省略 ...

再次运行,会发现修改属性会触发异常。

修改前: CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8')
Traceback (most recent call last):
File "D:\projects\python\samples\data_classes\main.py", line 66, in <module>
coin_trans.symbol = "ETH/USDT"
^^^^^^^^^^^^^^^^^
File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'symbol'

2.4. 转化为元组和字典

最后,dataclasses模块还提供了两个函数可以很方便的将数据类转换为元组字典
这在和其他分析程序交互时非常有用,因为和其他程序交互时,参数一般都用元组或者字典这种简单通用的结构,
而不会直接用自己定义的数据类。

from dataclasses import dataclass, field, astuple, asdict

if __name__ == "__main__":
coin_trans = CoinTrans()
print(astuple(coin_trans))
print(asdict(coin_trans))

运行结果:

('id01', 'BTC/USDT', '71000.8', True, ['0x1111', '0x2222'])
{'id': 'id01', 'symbol': 'BTC/USDT', 'price': '71000.8', 'is_success': True, 'addrs': ['0x1111', '0x2222']}

3. 总结

Python中,数据类主要用于存储数据,并通常包含属性和方法来操作这些数据。
然而,在定义数据类时,我们通常需要编写一些重复性的代码,如构造函数、属性访问器和字符串表示等。
dataclass装饰器的出现,使得这些通用方法的生成变得自动化,从而极大地简化了数据类的定义过程。

总的来说,dataclass通过简化数据类的创建和管理过程,提高了开发效率,是我们在数据分析时的一个非常有用的工具。

掌握python的dataclass,让你的代码更简洁优雅的更多相关文章

  1. Java 8 Lambda表达式,让你的代码更简洁

    Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...

  2. 巧用&&和|| 让逻辑代码更简洁,逼格看起来更高一点(玩笑脸)

    通常当我们有一个需求 需要用到很多if else 进行条件筛选,例如: let level = 0; if(score > 12){ level = 4; } else if(score > ...

  3. lombok ------让代码更简洁方便

    估计在平常写代码中,都会创建entity类的实体来,都是那种创建变量,生成set get 方法,方便外部调用,你以为你很流利的操作快捷键就很方便的了? 其实不然,有一个lombok 工具可以帮我们自动 ...

  4. try-with-resources 让java资源关闭代码更简洁

    一.JDK7的资源关闭方式优化 1 try-with-resource语法 在JDK7以前,Java没有自动关闭外部资源的语法特性,直到JDK7中新增了try-with-resource语法,才实现了 ...

  5. 利用margin代替小图标的绝对定位;使代码更简洁

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 从源代码分析modelDriven拦截器和params拦截器和拦截器prepare 和paramsPrepareParamsStack拦截器栈(让你的Struts2代码更简洁——如何培养框架设计能力

    源代码文件:Web App Libraries/struts2-core-2.3.15.3.jar/struts-default.xml 拦截器modelDriven: <interceptor ...

  7. SpringBoot集成lombook让代码更简洁

    1)添加lombok依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>l ...

  8. 全面吃透JAVA Stream流操作,让代码更加的优雅

    全面吃透JAVA Stream流操作,让代码更加的优雅 在JAVA中,涉及到对数组.Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行 ...

  9. 可爱的豆子——使用Beans思想让Python代码更易维护

    title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...

  10. Python实现各种排序算法的代码示例总结

    Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...

随机推荐

  1. 物联网浏览器(IoTBrowser)-MQTT协议集成和测试

    一.简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议.它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情 ...

  2. 零基础入门学习Java课堂笔记 ——day02

    流程控制 1.Scanner对象 来源:java.util.Scanner 我们可以通过Scanner类来获取用户的输入输出 用户交互Scanner 通过new关键词创建Scanner对象 Scann ...

  3. 使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序

    对于在线客服与营销系统,客服端指的是后台提供服务的客服或营销人员,他们使用客服程序在后台观察网站的被访情况,开展营销活动或提供客户服务.在本篇文章中,我将详细介绍如何通过 WPF + Chrome 内 ...

  4. Skywalking-Aop Docker单机环境搭建

    1.OAP-SERVER和UI环境搭建 本次搭建是基于MySQL进行持久化,因此需要提前准备好一个MySQL容器 (MySQL容器部署略过).如有错误还请指正. 1.1 OAP服务搭建 拉取skywa ...

  5. 从零开始学正则(七:终章),详解常用正则API与你可能不知道的正则坑

     壹 ❀ 引 花了差不多半个月的晚上时间,正则入门学习也步入尾声了,当然正则的学习还将继续.不得不说学习成效非常明显,已能看懂大部分正则以及写出不太复杂的正则,比如帮组长写正则验证文件路径正确性,再如 ...

  6. NC25045 [USACO 2007 Jan S]Balanced Lineup

    题目链接 题目 题目描述 For the daily milking, Farmer John's N cows (1 ≤ N ≤ 100,000) always line up in the sam ...

  7. 微信小程序生态13-微信公众号自定义菜单配置

    序 微信公众号分为订阅号和服务号两种,虽然二者很大的不同,但是这两种公众号的底部却是差不多的:都有菜单栏,而且这些底部菜单也都是自定义配置的. 如CSDN的官方公众号的底部就有精彩栏目.新程序员.CS ...

  8. Mac技巧之苹果电脑上将一个软件进程的 CPU 占用率限制在指定范围内:cputhrottle

    苹果电脑 Mac OS X 系统上,我们可以用 cputhrottle 这个免费工具,配合活动监视器和终端,把一个软件进程的 CPU 占用率限制在指定值(比如 20%)以内,以防止应为它 " ...

  9. Go语言并发编程(1):对多进程、多线程、协程和并发、并行的理解

    一.进程和线程 对操作系统进程和线程以及协程的了解,可以看看我前面的文章: 对进程.线程和协程的理解以及它们的区别:https://www.cnblogs.com/jiujuan/p/16193142 ...

  10. 深入理解Go语言(03):scheduler调度器 - 基本介绍

    一:什么是调度 平常我们在生活中会有哪些调度的例子呢?比如十字路口的红绿灯,它就是一种调度系统.在交通十字路口,每个路口上多多少少有一些车辆,为了限制这些车辆不随意行驶,就建起了红绿灯调度系统.红绿灯 ...