轻松掌握python的dataclass让你的代码更简洁优雅

2025-01-06 15:50

本文主要是介绍轻松掌握python的dataclass让你的代码更简洁优雅,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《轻松掌握python的dataclass让你的代码更简洁优雅》本文总结了几个我在使用Python的dataclass时常用的技巧,dataclass装饰器可以帮助我们简化数据类的定义过程,包括设置默...

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

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

1. 传统的类定义方式

首先,从平时量化分析的场景中简化一个关于&nbsphpp;币交易 的类用来演示。
简化之后,这里只保留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] =javascript ["0x1111javascript", "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))
    jsprint(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,让你的代码更简洁优雅的文章就介绍到这了,更多相关python dataclass内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于轻松掌握python的dataclass让你的代码更简洁优雅的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1152948

相关文章

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

python中cv2.imdecode()与cv2.imencode()的使用小结

《python中cv2.imdecode()与cv2.imencode()的使用小结》本文介绍了cv2.imencode()和cv2.imdecode()函数的使用,文中通过示例代码介绍的非常详细,对... 目录1、图片路径带中文的读取和写入1.1 读取1.2 写入2、在网络中传输图片cv2.imencod

Python使用asyncio实现异步操作的示例

《Python使用asyncio实现异步操作的示例》本文主要介绍了Python使用asyncio实现异步操作的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录1. 基础概念2. 实现异步 I/O 的步骤2.1 定义异步函数2.2 使用 await 等待异

python忽略warnings的几种方法

《python忽略warnings的几种方法》本文主要介绍了几种在Python忽略警告信息的方法,,可以使用Python内置的警告控制机制来抑制特定类型的警告,下面就来介绍一下,感兴趣的可以了解一下... 目录方法 1: 使用 warnings 模块过滤特定类型和消息内容的警告方法 2: 使用 warnin

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

python subprocess.run中的具体使用

《pythonsubprocess.run中的具体使用》subprocess.run是Python3.5及以上版本中用于运行子进程的函数,它提供了更简单和更强大的方式来创建和管理子进程,本文就来详细... 目录一、详解1.1、基本用法1.2、参数详解1.3、返回值1.4、示例1.5、总结二、subproce

python中poetry安装依赖

《python中poetry安装依赖》本文主要介绍了Poetry工具及其在Python项目中的安装和使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前言1. 为什么pip install poetry 会造成依赖冲突1.1 全局环境依赖混淆:1

Python中列表的高级索引技巧分享

《Python中列表的高级索引技巧分享》列表是Python中最常用的数据结构之一,它允许你存储多个元素,并且可以通过索引来访问这些元素,本文将带你深入了解Python列表的高级索引技巧,希望对... 目录1.基本索引2.切片3.负数索引切片4.步长5.多维列表6.列表解析7.切片赋值8.删除元素9.反转列表

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景