創(chuàng)建你的第一個數(shù)據(jù)類讓我們創(chuàng)建一個數(shù)據(jù)類,,該數(shù)據(jù)類表示3D坐標(biāo)系中的一個點(diǎn),。 @dataclass裝飾器用于創(chuàng)建數(shù)據(jù)類,。 x,y和z是我們數(shù)據(jù)類中的字段。 注意,你要用類型注釋來指定字段的數(shù)據(jù)類型,。記住,類型注釋不是靜態(tài)類型聲明,,這意味著有人可以為x,,y或z字段傳遞除int之外的任何數(shù)據(jù)類型。 from dataclasses import dataclass@dataclassclass Coordinate: x: int y: int z: int 默認(rèn)情況下,,數(shù)據(jù)類隨附實(shí)現(xiàn)了__init __,,__ repr__和__eq__方法,我們不需要自己來實(shí)現(xiàn)這些方法,。 但是__init__,,__repr__和__eq__沒有在Coordinate類中實(shí)現(xiàn),因?yàn)橛辛藬?shù)據(jù)類,,我們可以通過使用這些方法,,來大量節(jié)省時間。
字段的默認(rèn)值我們可以為字段分配默認(rèn)值。 在以下示例中,, 從pi字段可以看到,,我們可以為數(shù)據(jù)類中的字段分配默認(rèn)值。 from dataclasses import dataclass@dataclassclass CircleArea: r: int pi: float = 3.14 @property def area(self): return self.pi * (self.r ** 2)a = CircleArea(2)print(repr(a)) # 輸出:CircleArea(r = 2,,pi = 3.14)print(a.area) # 輸出: 12.56 自定義字段和數(shù)據(jù)類通過使用數(shù)據(jù)類裝飾器或字段函數(shù)的參數(shù),,可以自定義字段和數(shù)據(jù)類。我將在接下來的示例中自定義任何內(nèi)容時進(jìn)行說明,,并在本文結(jié)尾給出字段和數(shù)據(jù)類的所有參數(shù),。 數(shù)據(jù)類是可變的還是不可變的? 默認(rèn)情況下,,數(shù)據(jù)類是可變的,,這意味著我們可以為字段賦值。但是,,通過將凍結(jié)參數(shù)設(shè)置為True,,仍然可以使其不可變。 可變示例
不可變示例 當(dāng)我們將Frozen設(shè)置為True時,,我們將無法再為字段分配值,。 我們可以在以下示例中看到異常輸出。 from dataclasses import dataclass@dataclass(frozen=True)class CircleArea: r: int pi: float = 3.14 @property def area(self): return self.pi * (self.r ** 2)a = CircleArea(2)a.r = 5# 發(fā)生異常:dataclasses.FrozenInstanceError數(shù)據(jù)類:# 無法分配給字段“ r” 比較數(shù)據(jù)類假設(shè)你想創(chuàng)建一個表示向量的數(shù)據(jù)類,,并想要對它們進(jìn)行比較,。你會怎么做? 默認(rèn)情況下,,數(shù)據(jù)類的order參數(shù)為False,。當(dāng)你將其設(shè)置為True時,將自動為你的數(shù)據(jù)類生成方法,。因此,,你可以將對象作為其字段的元組順序進(jìn)行比較。 讓我們來研究下面的這個例子,。我們可以比較v2和v1,,因?yàn)槲覀儗rder設(shè)置為True。但這里有一個問題,,那就是比較的邏輯,。當(dāng)你說v2>v1時,,它比較這兩個向量,比如(8,,15)>(7,,20)。所以v2>v1的輸出是真的,。 回想一下,,元組比較是逐位置進(jìn)行的。它首先比較8到7,,結(jié)果為真,,然后比較結(jié)果為真。如果它們相等,,則比較15>20,,則結(jié)果為假。
在回顧元組是如何比較的之后,,很明顯這種比較沒有任何意義,。我想用向量的大小來比較它們。這里的問題是,,在創(chuàng)建每個實(shí)例時,,你不想去計(jì)算向量的大小。 在這種情況下,,我們將受益于field函數(shù)和__post_init__方法,。field函數(shù)將幫助我們自定義幅度場。__post_init__方法將幫助我們在初始化后確定該向量的大小,。 我們通過使用數(shù)據(jù)類中的字段函數(shù)來自定義幅度字段,。 通過將init設(shè)置為False,基本上我們不需要__init__方法中的幅度參數(shù),。 因?yàn)槲覀円诔跏蓟笫褂胈_post_init__方法確定其值 from dataclasses import dataclass, field@dataclass(order=True)class Vector: magnitude: float = field(init=False) x: int y: int def __post_init__(self): self.magnitude = (self.x ** 2 + self.y ** 2) ** 0.5v1 = Vector(9, 12)print(v1) # 輸出:矢量(幅值=15.0,,x=9,y=12)v2 = Vector(8, 15)print(v2) # output: Vector(magnitude=17.0, x=8, y=15)print(v2 > v1) # output: True 轉(zhuǎn)換為字典或元組你可以在元組或字典中獲取數(shù)據(jù)類的屬性,。 你所需要做的就是從數(shù)據(jù)類中導(dǎo)入asdict和astuple函數(shù),。
繼承你可以像Python中的普通類那樣對數(shù)據(jù)類進(jìn)行子類化。 from dataclasses import dataclass@dataclassclass Employee: name: str lang: str@dataclassclass Developer(Employee): salary: intHalil = Developer('Halil', 'Python', 5000)print(Halil) # 輸出:開發(fā)人員(名稱='Halil',,lang ='Python',,月薪= 5000) 使用繼承時有一個常見錯誤。 默認(rèn)情況下,,將lang字段設(shè)置為Python時,,必須為lang字段之后的字段提供默認(rèn)值。
為了了解原因,,讓我們看看我們的初始化方法是什么樣子的,?;叵胍幌拢哂心J(rèn)值的參數(shù)應(yīng)該在沒有默認(rèn)值的參數(shù)之后,。 def __init__(name: str, lang: str = 'Python', salary: int): ... 我們可以通過為salary字段提供默認(rèn)值來修復(fù)它,。
從插入的數(shù)據(jù)類中獲益默認(rèn)情況下,屬性存儲在字典中,。我們可以從插入的數(shù)據(jù)類中獲得更快的屬性,,訪問和使用更少的內(nèi)存。 from dataclasses import dataclass@dataclassclass Employee: name: str lang: strHalil = Employee('Halil', 'Python')print(Halil.__dict__) # name': 'Halil', 'lang': 'Python'} 我們可以使用插入數(shù)據(jù)類來使用更少的內(nèi)存并更快地訪問數(shù)據(jù)類屬性,。
數(shù)據(jù)類別參數(shù)我們更改了數(shù)據(jù)類修飾器中的某些參數(shù)以自定義數(shù)據(jù)類,。以下為參數(shù)列表:
請注意,如果order為True,,則eq必須為True,,否則將引發(fā)ValueError異常。 字段參數(shù)
結(jié)論以上所有內(nèi)容是對數(shù)據(jù)類的簡要介紹,如果你還在嫌棄Python運(yùn)行起來很慢,,很占內(nèi)存,,那不妨試試用數(shù)據(jù)類來解決這些問題。希望這些內(nèi)容對各位同學(xué)有幫助哈,! |
|