摘要:它的目標(biāo)就是在不減慢你編程速度的前提下,幫助你來編寫簡潔而又正確的代碼。對于這種情況,我們就需要有條件來控制某些屬性不能為非法值。所以,一定要在里面某個錯誤。
使用attrs解放雙手
大家好,這一期我想和大家分享一個OOP編程的高效神器:attrs庫
首先我們來介紹下 attrs 這個庫,其官方的介紹如下:
attrs 是這樣的一個 Python 工具包,它能將你從繁綜復(fù)雜的實現(xiàn)上解脫出來,享受編寫 Python 類的快樂。它的目標(biāo)就是在不減慢你編程速度的前提下,幫助你來編寫簡潔而又正確的代碼。
因此用了它,定義和實現(xiàn) Python 類變得更加簡潔和高效
首先明確一點,我們現(xiàn)在是裝了 attrs 和 cattrs 這兩個庫,但是實際導(dǎo)入的時候是使用 attr 和 cattr 這兩個包,是不帶 s 的。
在 attr 這個庫里面有兩個比較常用的組件叫做 attrs 和 attr,前者是主要用來修飾一個自定義類的,后者是定義類里面的一個字段的。下面是一個小例子
from attr import attrs,attrib @attrs class Person: name = attrib(type = str,default="") age = attrib(type = int,default=0) sex = attrib(type = str,default="") if __name__ == "__main__": first_person = Person("John",18,"M") print(first_person) Out:Person(name="John", age=18, sex="M")主要作用
可以發(fā)現(xiàn),Person這個類 三個屬性都只寫了一次,同時還指定了各個字段的類型和默認(rèn)值,另外也不需要再定義 init 方法和 repr 方法了,非常簡潔
實際上,主要是 attrs 這個修飾符起了作用,然后根據(jù)定義的 attrib 屬性自動幫我們實現(xiàn)了 init、repr、eq、ne、lt、le、gt、ge、hash 這幾個方法
深入了解現(xiàn)在來用實例看一下:
first_person = Person("John",18,"M") second_person = Person("Nancy",16,"F") print("Equal:", first_person == second_person) #False print("Not Equal(ne):", first_person != second_person) #True print("Less Than(lt):", first_person.age < second_person.age) #False print("Less or Equal(le):", first_person.age <= second_person.age) #False print("Greater Than(gt):", first_person.age > second_person.age) #True print("Greater or Equal(ge):", first_person.age >= second_person.age) #True屬性定義
對于 attrib 的定義,可以傳入各種參數(shù),不同的參數(shù)對于這個類的定義有非常大的影響。
下面來詳細(xì)了解一下每個屬性的具體參數(shù)和用法。
首先我們用 attrs 里面的 fields 方法可以查看一下
from attr import attrs, attrib,fields print(fields(Person)) (Attribute(name="name", default="", validator=None, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=, converter=None, kw_only=False), Attribute(name="age", default=0, validator=None, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type= , converter=None, kw_only=False), Attribute(name="sex", default="", validator=None, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type= , converter=None, kw_only=False))
參數(shù) | 解釋 |
---|---|
name | 屬性的名字,是一個字符串類型 |
default | 屬性的默認(rèn)值,如果沒有傳入初始化數(shù)據(jù),那么就會使用默認(rèn)值,如果沒有默認(rèn)值定義,那么就是 NOTHING,即沒有默認(rèn)值 |
validator | 驗證器,檢查傳入的參數(shù)是否合法 |
init | 是否參與初始化,如果為 False,那么這個參數(shù)不能當(dāng)做類的初始化參數(shù),默認(rèn)是 True。 |
type | 類型,比如 int、str 等各種類型,默認(rèn)為 None |
metadata | 元數(shù)據(jù),只讀性的附加數(shù)據(jù) |
converter | 轉(zhuǎn)換器,進(jìn)行一些值的處理和轉(zhuǎn)換器,增加容錯性 |
kw_only | 是否為強制關(guān)鍵字參數(shù),默認(rèn)為 False |
如果一個類的某些屬性不想?yún)⑴c初始化,比如想直接設(shè)置一個初始值,一直固定不變,我們可以將屬性的 init 參數(shù)設(shè)置為 False,看一個實例:
from attr import attrs,attrib @attrs class Person: name = attrib(type = str) age = attrib(init=False) sex = attrib(type = str) first = Person("John","M") # Person(name="John", age=NOTHING, sex="M") second = Person("Mike",89,"M") #TypeError: __init__() takes 3 positional arguments but 4 were given
可以發(fā)現(xiàn),first沒有問題,但是second會報錯,因為age沒有參與初始化,只剩了self,age,sex
強制關(guān)鍵字強制關(guān)鍵字是 Python 里面的一個特性,在傳入的時候必須使用關(guān)鍵字的名字來傳入
設(shè)置了強制關(guān)鍵字參數(shù)的屬性必須要放在后面,其后面不能再有非強制關(guān)鍵字參數(shù)的屬性
我們還是拿一樣的例子,這回把sex的參數(shù)
from attr import attrs,attrib @attrs class Person: name = attrib(type = str) age = attrib(type = str) sex = attrib(kw_only=True) first = Person("John",18,sex="M") #Person(name="John", age=18, sex="M")
如果初始化first時使用Person("John",18,"M")則會報錯
驗證器有時候在設(shè)置一個屬性的時候必須要滿足某個條件,比如性別必須要是男或者女,否則就不合法。對于這種情況,我們就需要有條件來控制某些屬性不能為非法值。
from attr import attrs, attrib def is_valid_gender(instance, attribute, value): if value not in ("M", "F"): raise ValueError(f"gender {value} is not valid") @attrs class Person: name = attrib(type = str) age = attrib(type = str) sex = attrib(validator=is_valid_gender)
在這里我們定義了一個驗證器 Validator 方法,叫做 is_valid_gender,其中 gender 定義的時候傳入了一個參數(shù) validator,其值就是我們定義的 Validator 方法:
instance:類對象
attribute:屬性名
value:屬性值
下面做了兩個實驗,一個就是正常傳入 "M",另一個寫錯了,寫的是 "X":
first = Person("John",18,"M") # Person(name="John", age=18, sex="M") second = Person("Ann",29,"X") ValueError: gender X is not valid
second報錯了,因為其值不是正常的性別,所以程序直接報錯終止
注意在 Validator 里面返回 True 或 False 是沒用的,錯誤的值還會被照常復(fù)制。所以,一定要在 Validator 里面 raise 某個錯誤。
另外 attrs 庫里面還給我們內(nèi)置了好多 Validator,比如判斷類型,這里如果規(guī)定age必須為 int 類型:
age =attrib(validator=validators.instance_of(int))
另外 validator 參數(shù)還支持多個 Validator,比如我們要設(shè)置既要是數(shù)字,又要小于 100,那么可以把幾個 Validator 放到一個列表里面并傳入:
from attr import attrs, attrib,validators def is_valid_gender(instance, attribute, value): if value not in ("M", "F"): raise ValueError(f"gender {value} is not valid") def is_less_than_100(instance, attribute, value): if value > 100: raise ValueError(f"age {value} must less than 100") @attrs class Person: name = attrib(type = str) age = attrib(validator=[validators.instance_of(int), is_less_than_100]) sex = attrib(validator=[validators.instance_of(str),is_valid_gender])轉(zhuǎn)換器
很多時候我們會不小心傳入一些形式不太標(biāo)準(zhǔn)的結(jié)果,比如本來是 int 類型的 100,我們傳入了字符串類型的 100,那這時候直接拋錯應(yīng)該不好吧,所以我們可以設(shè)置一些轉(zhuǎn)換器來增強容錯機制,比如將字符串自動轉(zhuǎn)為數(shù)字:
from attr import attrs, attrib,validators def to_int(value): try: return int(value) except: return None @attrs class Person: name = attrib(type = str) age = attrib(converter=to_int) sex = attrib(validator=validators.instance_of(str)) last_person = Person("xiaobai","35","M") print(last_person) Out: Person(name="xiaobai", age=35, sex="M")總結(jié)
這次我記錄了attrs 庫的用法,是參考了別人的文章,至此Python OOP 編程的個人學(xué)習(xí)經(jīng)歷都已經(jīng)記錄下來了
我的其他原創(chuàng)文章已經(jīng)放到了Github上,如果感興趣的朋友可以去看看,鏈接如下:
Python 精品練習(xí)題100道
Python 實用技巧匯總
Python Pandas教程
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/45200.html
摘要:大家好,上一期受到了朋友的啟發(fā),這一期我主要記錄一下我的的學(xué)習(xí)過程。 Dataclasses 大家好,上一期受到了朋友的啟發(fā),這一期我主要記錄一下我的Dataclasses的學(xué)習(xí)過程。 之前簡單回顧了attrs的用法,這一期來看更簡潔的自帶寫類神器:dataclasses,需要注意,版本要大于等于Python 3.7 官方文檔鏈接: Data Classes下面直接來看例子: 創(chuàng)建Da...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
摘要:面向?qū)ο缶幊讨镁幊淌鞘裁创蠹液茫鳛樾“祝罱鼘W(xué)習(xí)了很多編程的知識,因為腦容量有限,特此一一按照學(xué)習(xí)順序記錄下來,如果哪里有錯誤,還請大神盡快指出,以免誤導(dǎo)他人。。。繼承也允許把一個派生類的對象作為一個基類對象對待。 Python面向?qū)ο缶幊讨?OOP編程是什么 大家好,作為小白,最近學(xué)習(xí)了很多Python OOP編程的知識,因為腦容量有限,特此一一按照學(xué)習(xí)順序記錄下來,如果哪里有...
閱讀 1778·2023-04-25 14:33
閱讀 3378·2021-11-22 15:22
閱讀 2177·2021-09-30 09:48
閱讀 2684·2021-09-14 18:01
閱讀 1740·2019-08-30 15:55
閱讀 3006·2019-08-30 15:53
閱讀 2139·2019-08-30 15:44
閱讀 648·2019-08-30 10:58