本篇文章給大家分享的是有關(guān)Python中有哪些數(shù)據(jù)類,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
為海拉爾等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及海拉爾網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計制作、做網(wǎng)站、海拉爾網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
創(chuàng)建第一個數(shù)據(jù)類
創(chuàng)建一個數(shù)據(jù)類,該數(shù)據(jù)類表示三維坐標(biāo)系中的一個點。
@dataclass裝飾器用于創(chuàng)建數(shù)據(jù)類。x,y和z是數(shù)據(jù)類中的字段。注意要使用類型注釋來指定字段的數(shù)據(jù)類型,但是類型注釋不是靜態(tài)類型聲明,這意味著仍然可以為x,y或z字段傳遞除int之外的任何數(shù)據(jù)類型。
from dataclasses import dataclass @dataclass classCoordinate: x: int y: int z: int
默認(rèn)情況下,數(shù)據(jù)類附帶有init、repr和 eq方法,因此我們不必自己實現(xiàn)。但是如果init、repr和eq沒有在Coordinate類中實現(xiàn),有了數(shù)據(jù)類,我們?nèi)匀豢梢允褂眠@些方法,這樣非常節(jié)省時間。
from dataclasses import dataclass @dataclass classCoordinate: x: int y: int z: int a =Coordinate(4, 5, 3) print(a) # output: Coordinate(x=4, y=5, z=3)
字段的默認(rèn)值
編碼者可以為字段分配默認(rèn)值。如下所示,數(shù)據(jù)類中的pi字段被分配了默認(rèn)值:
from dataclasses import dataclass @dataclass classCircleArea: r: int pi: float =3.14 @property defarea(self): return self.pi * (self.r **2) a =CircleArea(2) print(repr(a)) # output: CircleArea(r=2, pi=3.14) print(a.area) # output: 12.56
自定義字段和數(shù)據(jù)類
設(shè)置dataclass裝飾器或field函數(shù)的參數(shù)可以自定義字段和數(shù)據(jù)類。自定義過程將用例子進行說明,本文結(jié)尾也會給出字段和數(shù)據(jù)類的所有參數(shù)。
數(shù)據(jù)類可變還是不可變?
默認(rèn)情況下,數(shù)據(jù)類是可變的,這意味著可以為字段分配值。但我們可以通過將frozen參數(shù)設(shè)置為True來使其不可變
可變示例:
from dataclasses import dataclass @dataclass classCircleArea: r: int pi: float =3.14 @property defarea(self): return self.pi * (self.r **2) a =CircleArea(2) a.r =5 print(repr(a)) # output: CircleArea(r=5, pi=3.14) print(a.area) # output: 78.5
不可變示例:
設(shè)置frozen為 True,將無法再為字段分配值。在下面的示例中可以看到異常輸出。
from dataclasses import dataclass @dataclass(frozen=True) classCircleArea: r: int pi: float =3.14 @property defarea(self): return self.pi * (self.r **2) a =CircleArea(2) a.r =5 # Exceptionoccurred: dataclasses.FrozenInstanceError: # cannot assign tofield 'r'
比較數(shù)據(jù)類
假設(shè)要創(chuàng)建一個表示Vector的數(shù)據(jù)類并進行比較,你會怎么做?當(dāng)然需要使用諸如lt或gt之類的方法啦。
默認(rèn)情況下,數(shù)據(jù)類的order參數(shù)為 False。將其設(shè)置為True,會自動為數(shù)據(jù)類生成 lt、le、gt和ge方法。因此,可以按順序比較對象,就像它們是其字段的元組一樣。
研究下面的示例:將order設(shè)置為True就可以比較v2和v1。這里存在一個邏輯比較的問題。當(dāng)v2> v1時,它將比較這兩個向量,例如(8,15)>(7,20)。因此,v2> v1的輸出將為True。
回想一下,元組比較是逐個按照順序進行的。首先將8和7進行比較,結(jié)果為True,那么比較結(jié)果就為True。如果它們相等,則比較15> 20,結(jié)果為False:
from dataclasses import dataclass,field @dataclass(order=True) classVector: x: int y: int v1 =Vector(8, 15) v2 =Vector(7, 20) print(v2 > v1)
顯然這種比較沒有任何意義。筆者最初想通過向量的大小來比較它們。但問題是,不可能在創(chuàng)建每個實例時,都要自己計算Vector的大小。
在這種情況下,field函數(shù)和post_init方法更有用。field函數(shù)能自定義magnitude字段。而post_init方法則會確定初始化后該矢量的大小。
還可以使用數(shù)據(jù)類中的field函數(shù)來自定義magnitude字段。通過將init設(shè)置為False,基本可以不需要init方法中的magnitude參數(shù)。因為初始化后才使用post_init方法來確定其值:
from dataclasses import dataclass, field @dataclass(order=True) classVector: magnitude: float =field(init=False) x: int y: int def__post_init__(self): self.magnitude = (self.x **2+ self.y **2) **0.5 v1 =Vector(9, 12) print(v1) # output: Vector(magnitude=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
將數(shù)據(jù)類轉(zhuǎn)換為字典或元組
從元組或字典中獲取數(shù)據(jù)類的屬性,只需要從數(shù)據(jù)類中導(dǎo)入asdict和astuple函數(shù):
from dataclasses import dataclass,asdict, astuple @dataclass classVector: x: int y: int z: int v =Vector(4, 5, 7) print(asdict(v)) # output: {'x': 4, 'y': 5, 'z': 7} print(astuple(v)) # output: (4, 5, 7)
繼承
可以像Python中的普通類一樣對數(shù)據(jù)類進行子類化:
from dataclasses import dataclass @dataclass classEmployee: name: str lang: str @dataclass classDeveloper(Employee): salary: int Halil=Developer('Halil', 'Python', 5000) print(Halil) # Output: Developer(name='Halil',lang='Python', salary=5000)
使用繼承時經(jīng)常會忽視一點:默認(rèn)情況下,當(dāng)將lang字段設(shè)置為Python時,必須為lang字段之后的字段提供默認(rèn)值:
from dataclasses import dataclass @dataclass classEmployee: name: str lang: str ='Python' @dataclass classDeveloper(Employee): salary: int Halil=Developer('Halil', 'Python', 5000) # Output:TypeError: non-default argument 'salary' follows default argument
原因在于init方法?;叵胍幌拢哂心J(rèn)值的參數(shù)應(yīng)該位于沒有默認(rèn)值的參數(shù)之后:
def__init__(name: str,lang: str ='Python', salary: int): ...
通過對sanlary字段設(shè)置默認(rèn)值來對其進行修復(fù):
from dataclasses import dataclass @dataclass classEmployee: name: str lang: str ='Python' @dataclass classDeveloper(Employee): salary: int =0 Halil=Developer('Halil', 'Python', 5000) print(Halil) # output: Developer(name='Halil',lang='Python', salary=5000)
slots的好處
默認(rèn)情況下,屬性存儲在字典中。使用slots可以更快地訪問屬性并且內(nèi)存占用更少。
from dataclasses import dataclass @dataclass classEmployee: name: str lang: str Halil=Employee('Halil', 'Python') print(Halil.__dict__) # name': 'Halil', 'lang': 'Python'}
slots內(nèi)存占用更小,訪問屬性更快。
from dataclasses import dataclass @dataclass classEmployee: __slots__ = ('name', 'lang') name: str lang: str Halil=Employee('Halil', 'Python')
數(shù)據(jù)類參數(shù)
剛剛我們更改了數(shù)據(jù)類裝飾器中的某些參數(shù),以自定義數(shù)據(jù)類。以下是參數(shù)列表:
nit:如果為True,則在數(shù)據(jù)類中生成init方法。(默認(rèn)為True)
repr:如果為True,則在數(shù)據(jù)類中生成repr方法。(默認(rèn)為True)
eq:如果為True,則在數(shù)據(jù)類中生成eq方法。(默認(rèn)為True)
order:如果為True,則在數(shù)據(jù)類中生成lt,le,gt和ge方法。(默認(rèn)為False)
unsafe_hash:如果為True,則在數(shù)據(jù)類中生成hash方法。(默認(rèn)為False)
frozen:如果為True,則不能給字段分配值。(默認(rèn)為False。)
注意,如果order為True,eq必須也為True,否則將引發(fā)ValueError異常。
字段參數(shù)
init:如果為True,則此字段包含在生成的init方法中。(默認(rèn)為True)
repr:如果為True,則此字段包含在生成的repr方法中。(默認(rèn)為True)
compare:如果為True,則此字段包含在生成的比較和相等方法中。(默認(rèn)為True)
hash:如果為True,則此字段包含在生成的hash方法中。(默認(rèn)為None)
default:這是此字段的默認(rèn)值(如果提供)。
default_factory:當(dāng)該字段需要默認(rèn)值時將調(diào)用該參數(shù),此時該參數(shù)必須為零階可調(diào)用參數(shù)對象。
metadata:可以是映射,也可以為空,為空則將其視為空字典。
以上就是Python中有哪些數(shù)據(jù)類,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。