dataclass
是從Python3.7
版本開始,作為標準庫中的模塊被引入。
隨著Python
版本的不斷更新,dataclass
也逐步發(fā)展和完善,為Python
開發(fā)者提供了更加便捷的數(shù)據(jù)類創(chuàng)建和管理方式。
dataclass
的主要功能在于幫助我們簡化數(shù)據(jù)類的定義過程。
本文總結了幾個我平時使用較多dataclass
技巧。
1. 傳統(tǒng)的類定義方式
首先,從平時量化分析的場景中簡化一個關于 幣交易 的類用來演示。
簡化之后,這里只保留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
傳統(tǒng)定義類的方式,如上通過__init__
函數(shù)來初始化對象的各個屬性。
通過這個類構造對象并打印:
if __name__ == "__main__":
coin_trans = CoinTrans("id01", "BTC/USDT", "71000", True, ["0x1111", "0x2222"])
print(coin_trans)
運行結果:
<__main__.CoinTrans object at 0x0000022A891FADD0>
這里只是打印出對象的地址,并沒有按照我們期望的那樣打印對象各個屬性的值。
傳統(tǒng)的類中,我們如果希望打印出可讀的結果,需要自己去實現(xiàn)__str__
函數(shù)。
# 在上面的 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)
運行之后發(fā)現(xiàn),在addrs
屬性那行會報錯:
ValueError: mutable default <class 'list'> for field addrs is not allowed: use default_factory
大概的意思就是,list
作為一種可變的類型(引用類型,會有被其他對象意外修改的風險),不能直接作為默認值,需要用工廠方法來產(chǎn)生默認值。
其他字符串,數(shù)值,布爾類型的數(shù)據(jù)則沒有這個問題。
我們只要定義個函數(shù)來產(chǎn)生此默認值即可。
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)
再次運行,可以正常執(zhí)行:
CoinTrans(id='id01', symbol='BTC/USDT', price='71000.8', is_success=True, addrs=['0x1111', '0x2222']
2.2. 隱藏敏感信息
我們打印對象信息的時候,有時執(zhí)行打印其中幾個屬性的信息,涉及敏感信息的屬性不希望打印出來。
比如,上面的對象,如果不想打印出is_success
和addrs
的信息,可以設置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. 只讀對象
數(shù)據(jù)分析時,大部分下情況下,原始數(shù)據(jù)讀取之后是不能修改的。
這種情況下,我們可以用dataclass
的frozen
屬性來設置數(shù)據(jù)類只讀,防止不小心篡改了數(shù)據(jù)。
未設置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"
#... 省略 ...
再次運行,會發(fā)現(xiàn)修改屬性會觸發(fā)異常。
修改前: 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
模塊還提供了兩個函數(shù)可以很方便的將數(shù)據(jù)類轉換為元組和字典。
這在和其他分析程序交互時非常有用,因為和其他程序交互時,參數(shù)一般都用元組或者字典這種簡單通用的結構,
而不會直接用自己定義的數(shù)據(jù)類。
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
中,數(shù)據(jù)類主要用于存儲數(shù)據(jù),并通常包含屬性和方法來操作這些數(shù)據(jù)。
然而,在定義數(shù)據(jù)類時,我們通常需要編寫一些重復性的代碼,如構造函數(shù)、屬性訪問器和字符串表示等。dataclass
裝飾器的出現(xiàn),使得這些通用方法的生成變得自動化,從而極大地簡化了數(shù)據(jù)類的定義過程。文章來源:http://www.zghlxwxcb.cn/news/detail-840658.html
總的來說,dataclass
通過簡化數(shù)據(jù)類的創(chuàng)建和管理過程,提高了開發(fā)效率,是我們在數(shù)據(jù)分析時的一個非常有用的工具。文章來源地址http://www.zghlxwxcb.cn/news/detail-840658.html
到了這里,關于掌握python的dataclass,讓你的代碼更簡潔優(yōu)雅的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!