当前位置: 代码网 > it编程>前端脚本>Python > 轻松掌握python的dataclass让你的代码更简洁优雅

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

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

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,让你的代码更简洁优雅的文章就介绍到这了,更多相关python dataclass内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com