這是 Python 最新的 Dataclasses 系列的第二部分內(nèi)容。在第一部分里边翼,我介紹了dataclasses
的一般用法胆绊。這篇博客主要介紹另一個特征:dataclasses.field
。
我們已經(jīng)知道Dataclasses
會生成他們自身的__init__
方法聪轿。它同時把初始化的值賦給這些字段煤惩。以下是我們在上一篇博客里定義的內(nèi)容:
變量名
數(shù)據(jù)類型
這些內(nèi)容僅給我們有限的 dataclass
字段使用范圍嫉嘀。讓我們討論一下這些局限性,以及它們?nèi)绾瓮ㄟ^ dataclass.field
被解決魄揉。
復(fù)合初始化
考慮以下情形:你想要初始化一個變量為列表。你如何實(shí)現(xiàn)它呢拭宁?一種簡單的方式是使用__post_init__
方法洛退。
數(shù)據(jù)類
Student
產(chǎn)生了一個名為marks
的列表。我們不傳遞 marks
的值杰标,而是使用__post_init__
方法初始化兵怯。這是我們定義的單一屬性。此外腔剂,我們必須在__post_init__
里調(diào)用get_random_marks
函數(shù)媒区。這些工作是額外的。
辛運(yùn)的是掸犬,Python
為我們提供了一個解決方案袜漩。我們可以使用dataclasses.field
來定制化 dataclass
字段的行為以及它們在dataclass
的影響。
仍然是上述的使用情形湾碎,讓我們從__post_init__
里去除 get_random_marks
的調(diào)用宙攻。以下是使用dataclasses.field
的情形:
dataclasses.field
接受了一個名為default_factory
的參數(shù),它的作用是:如果在創(chuàng)建對象時沒有賦值介褥,則使用該方法初始化該字段座掘。
default_factory
必須是一個可以調(diào)用的無參數(shù)方法(通常為一個函數(shù))。
這樣我們就可以使用復(fù)合形式初始化字段∪崽希現(xiàn)在溢陪,讓我們考慮另一個使用場景。
使用全部字段進(jìn)行數(shù)據(jù)比較
通過上篇博文睛廊,我們了解到形真,dataclass
能夠自動生成<
,=,
>
, <=
和>=
這些比較方法。但是這些比較方法的一個缺陷是喉前,它們使用類中的所有字段進(jìn)行比較没酣,而這種情況往往不常見王财。更經(jīng)常地,這種比較方法會給我們使用 dataclasses
造成麻煩裕便。
考慮以下的使用情形:你有一個數(shù)據(jù)類用于存放用戶的信息∪蘧唬現(xiàn)在,它可能存在以下字段:
姓名
年齡
身高
體重
你僅想比較用戶對象的年齡偿衰、身高和體重挂疆。你不想比較姓名。這是后端開發(fā)者經(jīng)常會遇到的使用情景下翎。
自動生成的比較方法會比較一下的數(shù)組:
這將會破壞我們的意圖缤言。我們不想讓姓名(name)
用于比較。那么视事,如何使用 dataclasses.field
來實(shí)現(xiàn)我們的想法呢胆萧?
下面是具體步驟:
默認(rèn)情況下,所用的字段都用于比較俐东,因此我們僅僅需要指定哪些字段用于比較跌穗,而實(shí)現(xiàn)方法是直接把不需要的字段定義為
filed(compare=False)
。
一個更為簡單的應(yīng)用情形也可以被討論虏辫。讓我們定義一個數(shù)據(jù)類蚌吸,它被用來存儲一個數(shù)字激起字符串表示。我們想讓比較僅僅發(fā)生在該數(shù)字的值砌庄,而不是他的字符串表示羹唠。
現(xiàn)在,我們有更大的自由來控制 dataclasses 的行為娄昆∨逦ⅲ看起來很棒!
使用全部字段進(jìn)行數(shù)據(jù)表示
自動生成的__repr__
方法使用所有的字段用于表示稿黄。當(dāng)然喊衫,這也不是大多數(shù)情形下的理想選擇,尤其是當(dāng)你的數(shù)據(jù)類有大量的字段時杆怕。單個對象的表示會變得異常臃腫族购,對調(diào)試來說也不利。
想象一下在你的日志里看到這樣的表示吧陵珍,然后還要寫一個正則表達(dá)式來搜索它寝杖。太可怕了,對吧互纯?
當(dāng)然瑟幕,我們也能夠個性化這種行為。考慮一個類似的使用場景只盹,也許最合適的用于表示的屬性是姓名(name)辣往。那么對__repr__
,我們僅使用它:
這樣看起來就很棒了殖卑。調(diào)試很方便站削,比較也有意義!
從初始化中省略字段
目前為止我們看到的所有例子孵稽,都有一個共同特點(diǎn)——即我們需要為所有被聲明的字段傳遞值许起,除了有默認(rèn)值之外。在那種情形下(指有默認(rèn)值的情況下)菩鲜,我們可以選擇傳遞值园细,也可以不傳遞。
但是接校,還有一種情形:我們可能不想在初始化時設(shè)定某個字段的值猛频。這也是一種常見的使用場景。也許你在追蹤一個對象的狀態(tài)馅笙,并且希望它在初始化時一直被設(shè)為
False
伦乔。更一般地,這個值在初始化時不能夠被傳遞董习。那么,我們?nèi)绾螌?shí)現(xiàn)上述想法呢爱只?以下是具體內(nèi)容:
瞧懊罅堋!我們現(xiàn)在對dataclasses
的使用有了更大的靈活性恬试。
總結(jié)
希望上兩篇博文能夠幫助你理解dataclass
窝趣,希望你能盡快在項(xiàng)目中使用它們!
感謝你的閱讀训柴。