
01
引言
大家好,我是AI算法之道!
Python是我最喜欢的编程语言之一,它向来以其简单性、多功能性和可读性而闻名。

大家好!今天我想与大家分享Python3.7引入的标准库dataclass模块,其主要功能是帮助大家简化数据类的定义过程。
闲话少说,我们直接开始吧!
02
传统类的定义
class CoinTrans:def __init__(self,id: str,symbol: str,price: float,is_success: bool,addrs: list,) -> None:self.id = idself.symbol = symbolself.price = priceself.addrs = addrsself.is_success = is_success
if __name__ == "__main__":coin_trans = CoinTrans("id01", "BTC/USDT", "71000", True, ["0x1111", "0x2222"])print(coin_trans)
结果如下:
<__main__.CoinTrans object at 0x0000022A891FADD0>
在这里,我们只打印出了对象的地址,而不是像预期的那样打印每个对象的属性值。
在传统的类中,如果我们想打印可读的结果,就需要自己实现 __str__ 函数。
# Add the following method to the CoinTrans class above.def __str__(self) -> str:return f"Transaction Information:{self.id}, {self.symbol}, {self.price}, {self.addrs}, {self.is_success}"
再次运行后,结果如下:
Trade information: id01, BTC/USDT, 71000, ['0x1111', '0x2222'], True
03
使用dataclass定义类
from dataclasses import dataclass@dataclassclass CoinTrans:id: strsymbol: strprice: floatis_success: booladdrs: 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 装饰,就能打印出对象的具体内容。
04
设置默认值
需使用dataclass装饰器来定义类,可以非常简单地设置默认值,您可以在定义属性时直接设置默认值。
例如,例子为:
@dataclassclass CoinTrans:id: str = "id01"symbol: str = "BTC/USDT"price: float = "71000.8"is_success: bool = Trueaddrs: list[str] = ["0x1111", "0x2222"]if __name__ == "__main__":coin_trans = CoinTrans()print(coin_trans)
ValueError: mutable default <class 'list'> for field addrs is not allowed: use default_factory
简单地说,其含义是作为可变类型(引用类型,有可能被其他对象无意修改)的列表不能直接用作默认值,而需要使用工厂方法生成。这个问题不适用于字符串、数字和布尔等其他数据类型。
为了解决上述问题,我们只需定义一个函数来生成默认值。
def gen_list():return ["0x1111", "0x2222"]class CoinTrans:id: str = "id01"symbol: str = "BTC/USDT"price: float = "71000.8"is_success: bool = Trueaddrs: 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']
05
隐藏敏感信息
在打印对象信息时,有时我们只打印某些属性的信息,而不想打印敏感信息。例如,对于上述对象,如果不想打印 "is_success "和 "addrs "的信息,可以设置 repr=False。
比如:
@dataclassclass 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')
06
只读对象
if __name__ == "__main__":coin_trans = CoinTrans()print(f"Before modification: {coin_trans}")coin_trans.symbol = "ETH/USDT"print(f"after modification: {coin_trans}")
结果如下:
Original: CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8')Modified: CoinTrans(id='id01', symbol='ETH/USDT', price='71000.8')
设置冻结属性后,看看修改属性值会发生什么:
class CoinTrans:id: str = "id01"#... omission ...
再次运行时,会发现修改属性会触发异常。
Before modification: 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'
07
转换为元组或字典
from dataclasses import dataclass, field, astuple, asdictif __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']}
08
总结
在 Python 中,数据类主要用于存储数据,通常包含对这些数据进行操作的属性和方法。然而,在定义传统数据类时,我们经常需要编写一些重复的代码,如构造函数、属性访问函数和字符串表示法。
dataclass装饰器的出现自动生成了这些常用方法,大大简化了数据类的定义过程。
总之,简化dataclass 的创建和管理过程可以提高开发效率,是数据分析的一种有用工具。
点击上方小卡片关注我
添加个人微信,进专属粉丝群!


