Python attrs提高面向?qū)ο缶幊绦试敿?/h1>
更新時間:2021年09月27日 08:57:04 作者:tigeriaf
Python是面向?qū)ο蟮恼Z言,一般情況下使用面向?qū)ο缶幊虝沟瞄_發(fā)效率更高,軟件質(zhì)量更好,并且代碼更易于擴展,可讀性和可維護性也更高,但是Python的類寫起來是真的累,這是可以在創(chuàng)建類的時候自動添加上attrs模塊,下面文章我們就來介紹這個東西,需要的朋友可參考一下
前言:
Python是面向?qū)ο蟮恼Z言,一般情況下使用面向?qū)ο缶幊虝沟瞄_發(fā)效率更高,軟件質(zhì)量更好,并且代碼更易于擴展,可讀性和可維護性也更高。但是如果在一個較大的項目中,如果實體類非常多并且有非常復雜的屬性,你就會逐漸覺得Python的類寫起來是真·“累”。為什么這樣說,看下下面這個Box
類,屬性有長(length
)、寬(width
)、高(hight
):
class Box:
def __init__(self, length, width, hight):
self.length = length
self.width = width
self.hight = hight
這樣倒沒有什么問題,而且是符合Python
規(guī)范的寫法,初始化函數(shù)內(nèi)每一個參數(shù)都需要用self.xxx = xxx
進行賦值,參數(shù)少了還好,但是如果參數(shù)過多了,只是參數(shù)賦值操作都夠?qū)懸粫牧?,如果一個項目中類也有很多,那就真的要麻木了。
而且我們知道,在Python
中,想要自定義對象本身的打印輸出結(jié)果的時候,需要在它的類中實現(xiàn)__repr__()
方法,例如:
def __repr__(self):
return '{}(length={}, width={}, hight={})'.format(
self.__class__.__name__, self.length, self.width, self.hight)
實現(xiàn)了__repr__()
方法,當我們打印對象本身的時候,才會輸出我們自定義的字符。
box = Box(20, 15, 15)
print(box)
# 結(jié)果輸出為 Box(length=20, width=15, hight=15)
但是有時會因為麻煩,我們不愿意去實現(xiàn)__repr__()
方法,但是不實現(xiàn)打印結(jié)果又不友好,就陷入了糾結(jié)之中。
如果我么想要實現(xiàn)對象比較,有時候需要判斷2個對象是否相等或者比較大小,就要實現(xiàn)__eq__()
、 __lt__()
、__gt__()
等各種方法來實現(xiàn)對象之間的比較,例如:
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return (self.length, self.width, self.hight) == (
other.length, other.width, other.hight)
這樣我們又需要實現(xiàn)這幾個用于比較的方法。 比如說我們已經(jīng)實現(xiàn)了上面說過的所有方法,然后又突然添加一個屬性結(jié)實度hardness,那么整個類的方法都需要修改,這是非常折磨人的。 那么有沒有一種方法,可以在創(chuàng)建類的時候自動添加上類似于上面提到的這些東西,答案是有的,那就是我們接下來要介紹的attrs
模塊,它可以幫助我們很方便的定義類。
1、attrs的使用
我們可以使用pip install attrs
進行安裝。
然后將上面的代碼改造一下:
from attr import attrs, attrib
@attrs
class Box:
length = attrib(type=int, default=0)
width = attrib(type=int, default=0)
hight = attrib(type=int, default=0)
box1 = Box(20, 15, 15)
print(box1)
box2 = Box(30, 20, 20)
print(box2 == box1)
print(box2 > box1)
用模塊內(nèi)的attrs
修飾了Box類,再使用attrib
定義所有的屬性,同時指定了屬性的類型和默認值。而且我們沒有實現(xiàn)任何一個上面所提到的方法,但是確實實現(xiàn)了所有的功能。 現(xiàn)在如果我們添加一個屬性顏色color
,這個屬性不參與對象的比較,但是打印的時候要輸出,添加一個屬性結(jié)實度hardness
,這個屬性參與對象的比較,但是打印對象的時候不輸出,就非常簡單了:
from attr import attrs, attrib
@attrs
class Box:
length = attrib(type=int, default=0)
width = attrib(type=int, default=0)
hight = attrib(type=int, default=0)
color = attrib(repr=True, cmp=False, default=(0, 0, 0))
hardness = attrib(repr=False, cmp=True, default=0)
box1 = Box(20, 15, 15, (255, 255, 255), 80)
print("box1:", box1)
box2 = Box(20, 15, 15, (255, 255, 0), 100)
print("box2:", box2)
print(box2 == box1)
print(box2 > box1)
執(zhí)行結(jié)果為:

也就是說,如果我們用了attrs庫的話,會讓類的定義變得高效簡潔,就不需要再寫哪些冗余又復雜的代碼了。 關(guān)于attrib()
,接收以下參數(shù):
default
:屬性的默認值,如果沒有傳入初始化數(shù)據(jù),那么就會使用默認值
validator
:驗證器,檢查傳入的參數(shù)是否合法
repr
:是否參與對象打印時的輸出
cmp
:是否參與對象比較
hash
:是否進行去重
init
:是否參與初始化,如果為False,那么這個參數(shù)不能當做類的初始化參數(shù),默認是True
metadata
:元數(shù)據(jù),只讀性的附加數(shù)據(jù)
type
:類型,比如 int、str 等各種類型,默認為 None
converter
:轉(zhuǎn)換器,進行一些值的處理和轉(zhuǎn)換器,增加容錯性
kw_only
:是否為強制關(guān)鍵字參數(shù),默認為 False
這里我們只重點說一下驗證器和轉(zhuǎn)換器,其他的參數(shù)都很好理解。
2、驗證器
有時候在設(shè)置一個屬性的時候必須要滿足某個條件,比如上面的顏色color
屬性,我們使用的是RGB三原色方式,例如黑色是(255,255,255),對于這種情況,我們就需要驗證屬性是否合法。
例如:
def color_is_valid(instance, attr, value):
if not isinstance(value, set):
raise ValueError(f"參數(shù){attr.name}:{value}不合法!")
for i in value:
if not 0 <= i<= 255:
raise ValueError(f"參數(shù){attr.name}:{value}不合法!")
@attrs
class Box:
length = attrib(type=int, default=0)
width = attrib(type=int, default=0)
hight = attrib(type=int, default=0)
color = attrib(repr=True, cmp=False, validator=color_is_valid, default=(0, 0, 0))
hardness = attrib(repr=False, cmp=True, default=0)
box1 = Box(20, 15, 15, (255, 255, 260), 80)
執(zhí)行結(jié)果為:

上述代碼中定義了一個驗證器color_is_valid()
方法來驗證顏色color
是否合法,不合法時就會拋異常。
驗證器方法接收三個參數(shù):
instance
:類對象
attr
:屬性名
value
:屬性值
而且attrs
模塊也提供了許多內(nèi)置驗證器,這里就不做贅述了。
3、轉(zhuǎn)換器
轉(zhuǎn)換器主要做一些值的處理和轉(zhuǎn)換,增加類的容錯性,比如一個屬性接收的是int類型,我們想要的是傳入了數(shù)字字符串也不會報錯,那我們就可以增加轉(zhuǎn)換器,將字符串自動轉(zhuǎn)為數(shù)字,例如:
def to_int(value):
try:
return int(value)
except:
return None
@attrs
class Box:
length = attrib(type=int, default=0, converter=to_int)
width = attrib(type=int, default=0, converter=to_int)
hight = attrib(type=int, default=0)
color = attrib(repr=True, cmp=False, default=(0, 0, 0))
hardness = attrib(repr=False, cmp=True, default=0)
box1 = Box("20", "15", 15, (255, 255, 255), 80)
print("box1:", box1)
box2 = Box("2a", 15, 15, (255, 255, 0), 100)
print("box2:", box2)

上面定義了一個方法to_int()
,可以將值轉(zhuǎn)化為數(shù)字類型,轉(zhuǎn)換異常就返回None
,這樣容錯性非常高了。
到此這篇關(guān)于Python attrs
提高面向?qū)ο缶幊绦试敿毜奈恼戮徒榻B到這了,更多相關(guān)Python attrs提高面向?qū)ο缶幊绦蕛?nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
使用matplotlib繪制并排柱狀圖的實戰(zhàn)案例
堆積柱狀圖有堆積柱狀圖的好處,比如說我們可以很方便地看到多分類總和的趨勢,下面這篇文章主要給大家介紹了關(guān)于使用matplotlib繪制并排柱狀圖的相關(guān)資料,需要的朋友可以參考下 2022-07-07
-
Python+OpenCV繪制多instance的Mask圖像
Mask圖像中,不同值表示不同的實例(instance)。本文將詳細為大家講講如何利用OpenCV繪制多instance的Mask圖像,感興趣的可以學習一下 2022-06-06
-
Python實現(xiàn)從log日志中提取ip的方法【正則提取】
這篇文章主要介紹了Python實現(xiàn)從log日志中提取ip的方法,涉及Python文件讀取、數(shù)據(jù)遍歷、正則匹配等相關(guān)操作技巧,需要的朋友可以參考下 2018-03-03
-
Django解決無法從request.POST中獲取URL傳進來的參數(shù)
這篇文章主要介紹了Django解決無法從request.POST中獲取URL傳進來的參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教 2023-12-12
最新評論
前言:
Python是面向?qū)ο蟮恼Z言,一般情況下使用面向?qū)ο缶幊虝沟瞄_發(fā)效率更高,軟件質(zhì)量更好,并且代碼更易于擴展,可讀性和可維護性也更高。但是如果在一個較大的項目中,如果實體類非常多并且有非常復雜的屬性,你就會逐漸覺得Python的類寫起來是真·“累”。為什么這樣說,看下下面這個Box
類,屬性有長(length
)、寬(width
)、高(hight
):
class Box: def __init__(self, length, width, hight): self.length = length self.width = width self.hight = hight
這樣倒沒有什么問題,而且是符合Python
規(guī)范的寫法,初始化函數(shù)內(nèi)每一個參數(shù)都需要用self.xxx = xxx
進行賦值,參數(shù)少了還好,但是如果參數(shù)過多了,只是參數(shù)賦值操作都夠?qū)懸粫牧?,如果一個項目中類也有很多,那就真的要麻木了。
而且我們知道,在Python
中,想要自定義對象本身的打印輸出結(jié)果的時候,需要在它的類中實現(xiàn)__repr__()
方法,例如:
def __repr__(self): return '{}(length={}, width={}, hight={})'.format( self.__class__.__name__, self.length, self.width, self.hight)
實現(xiàn)了__repr__()
方法,當我們打印對象本身的時候,才會輸出我們自定義的字符。
box = Box(20, 15, 15) print(box) # 結(jié)果輸出為 Box(length=20, width=15, hight=15)
但是有時會因為麻煩,我們不愿意去實現(xiàn)__repr__()
方法,但是不實現(xiàn)打印結(jié)果又不友好,就陷入了糾結(jié)之中。
如果我么想要實現(xiàn)對象比較,有時候需要判斷2個對象是否相等或者比較大小,就要實現(xiàn)__eq__()
、 __lt__()
、__gt__()
等各種方法來實現(xiàn)對象之間的比較,例如:
def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return (self.length, self.width, self.hight) == ( other.length, other.width, other.hight)
這樣我們又需要實現(xiàn)這幾個用于比較的方法。 比如說我們已經(jīng)實現(xiàn)了上面說過的所有方法,然后又突然添加一個屬性結(jié)實度hardness,那么整個類的方法都需要修改,這是非常折磨人的。 那么有沒有一種方法,可以在創(chuàng)建類的時候自動添加上類似于上面提到的這些東西,答案是有的,那就是我們接下來要介紹的attrs
模塊,它可以幫助我們很方便的定義類。
1、attrs的使用
我們可以使用pip install attrs
進行安裝。
然后將上面的代碼改造一下:
from attr import attrs, attrib @attrs class Box: length = attrib(type=int, default=0) width = attrib(type=int, default=0) hight = attrib(type=int, default=0) box1 = Box(20, 15, 15) print(box1) box2 = Box(30, 20, 20) print(box2 == box1) print(box2 > box1)
用模塊內(nèi)的attrs
修飾了Box類,再使用attrib
定義所有的屬性,同時指定了屬性的類型和默認值。而且我們沒有實現(xiàn)任何一個上面所提到的方法,但是確實實現(xiàn)了所有的功能。 現(xiàn)在如果我們添加一個屬性顏色color
,這個屬性不參與對象的比較,但是打印的時候要輸出,添加一個屬性結(jié)實度hardness
,這個屬性參與對象的比較,但是打印對象的時候不輸出,就非常簡單了:
from attr import attrs, attrib @attrs class Box: length = attrib(type=int, default=0) width = attrib(type=int, default=0) hight = attrib(type=int, default=0) color = attrib(repr=True, cmp=False, default=(0, 0, 0)) hardness = attrib(repr=False, cmp=True, default=0) box1 = Box(20, 15, 15, (255, 255, 255), 80) print("box1:", box1) box2 = Box(20, 15, 15, (255, 255, 0), 100) print("box2:", box2) print(box2 == box1) print(box2 > box1)
執(zhí)行結(jié)果為:
也就是說,如果我們用了attrs庫的話,會讓類的定義變得高效簡潔,就不需要再寫哪些冗余又復雜的代碼了。 關(guān)于attrib()
,接收以下參數(shù):
default
:屬性的默認值,如果沒有傳入初始化數(shù)據(jù),那么就會使用默認值validator
:驗證器,檢查傳入的參數(shù)是否合法repr
:是否參與對象打印時的輸出cmp
:是否參與對象比較hash
:是否進行去重init
:是否參與初始化,如果為False,那么這個參數(shù)不能當做類的初始化參數(shù),默認是Truemetadata
:元數(shù)據(jù),只讀性的附加數(shù)據(jù)type
:類型,比如 int、str 等各種類型,默認為 Noneconverter
:轉(zhuǎn)換器,進行一些值的處理和轉(zhuǎn)換器,增加容錯性kw_only
:是否為強制關(guān)鍵字參數(shù),默認為 False
這里我們只重點說一下驗證器和轉(zhuǎn)換器,其他的參數(shù)都很好理解。
2、驗證器
有時候在設(shè)置一個屬性的時候必須要滿足某個條件,比如上面的顏色color
屬性,我們使用的是RGB三原色方式,例如黑色是(255,255,255),對于這種情況,我們就需要驗證屬性是否合法。
例如:
def color_is_valid(instance, attr, value): if not isinstance(value, set): raise ValueError(f"參數(shù){attr.name}:{value}不合法!") for i in value: if not 0 <= i<= 255: raise ValueError(f"參數(shù){attr.name}:{value}不合法!") @attrs class Box: length = attrib(type=int, default=0) width = attrib(type=int, default=0) hight = attrib(type=int, default=0) color = attrib(repr=True, cmp=False, validator=color_is_valid, default=(0, 0, 0)) hardness = attrib(repr=False, cmp=True, default=0) box1 = Box(20, 15, 15, (255, 255, 260), 80)
執(zhí)行結(jié)果為:
上述代碼中定義了一個驗證器color_is_valid()
方法來驗證顏色color
是否合法,不合法時就會拋異常。
驗證器方法接收三個參數(shù):
instance
:類對象attr
:屬性名value
:屬性值
而且attrs
模塊也提供了許多內(nèi)置驗證器,這里就不做贅述了。
3、轉(zhuǎn)換器
轉(zhuǎn)換器主要做一些值的處理和轉(zhuǎn)換,增加類的容錯性,比如一個屬性接收的是int類型,我們想要的是傳入了數(shù)字字符串也不會報錯,那我們就可以增加轉(zhuǎn)換器,將字符串自動轉(zhuǎn)為數(shù)字,例如:
def to_int(value): try: return int(value) except: return None @attrs class Box: length = attrib(type=int, default=0, converter=to_int) width = attrib(type=int, default=0, converter=to_int) hight = attrib(type=int, default=0) color = attrib(repr=True, cmp=False, default=(0, 0, 0)) hardness = attrib(repr=False, cmp=True, default=0) box1 = Box("20", "15", 15, (255, 255, 255), 80) print("box1:", box1) box2 = Box("2a", 15, 15, (255, 255, 0), 100) print("box2:", box2)
上面定義了一個方法to_int()
,可以將值轉(zhuǎn)化為數(shù)字類型,轉(zhuǎn)換異常就返回None
,這樣容錯性非常高了。
到此這篇關(guān)于Python attrs
提高面向?qū)ο缶幊绦试敿毜奈恼戮徒榻B到這了,更多相關(guān)Python attrs提高面向?qū)ο缶幊绦蕛?nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用matplotlib繪制并排柱狀圖的實戰(zhàn)案例
堆積柱狀圖有堆積柱狀圖的好處,比如說我們可以很方便地看到多分類總和的趨勢,下面這篇文章主要給大家介紹了關(guān)于使用matplotlib繪制并排柱狀圖的相關(guān)資料,需要的朋友可以參考下2022-07-07Python+OpenCV繪制多instance的Mask圖像
Mask圖像中,不同值表示不同的實例(instance)。本文將詳細為大家講講如何利用OpenCV繪制多instance的Mask圖像,感興趣的可以學習一下2022-06-06Python實現(xiàn)從log日志中提取ip的方法【正則提取】
這篇文章主要介紹了Python實現(xiàn)從log日志中提取ip的方法,涉及Python文件讀取、數(shù)據(jù)遍歷、正則匹配等相關(guān)操作技巧,需要的朋友可以參考下2018-03-03Django解決無法從request.POST中獲取URL傳進來的參數(shù)
這篇文章主要介紹了Django解決無法從request.POST中獲取URL傳進來的參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12