欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python attrs提高面向?qū)ο缶幊绦试敿?xì)

 更新時(shí)間:2021年09月27日 08:57:04   作者:tigeriaf  
Python是面向?qū)ο蟮恼Z言,一般情況下使用面向?qū)ο缶幊虝?huì)使得開發(fā)效率更高,軟件質(zhì)量更好,并且代碼更易于擴(kuò)展,可讀性和可維護(hù)性也更高,但是Python的類寫起來是真的累,這是可以在創(chuàng)建類的時(shí)候自動(dòng)添加上attrs模塊,下面文章我們就來介紹這個(gè)東西,需要的朋友可參考一下

前言:

Python是面向?qū)ο蟮恼Z言,一般情況下使用面向?qū)ο缶幊虝?huì)使得開發(fā)效率更高,軟件質(zhì)量更好,并且代碼更易于擴(kuò)展,可讀性和可維護(hù)性也更高。但是如果在一個(gè)較大的項(xiàng)目中,如果實(shí)體類非常多并且有非常復(fù)雜的屬性,你就會(huì)逐漸覺得Python的類寫起來是真·“累”。為什么這樣說,看下下面這個(gè)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)每一個(gè)參數(shù)都需要用self.xxx = xxx進(jìn)行賦值,參數(shù)少了還好,但是如果參數(shù)過多了,只是參數(shù)賦值操作都?jí)驅(qū)懸粫?huì)的了,如果一個(gè)項(xiàng)目中類也有很多,那就真的要麻木了。

而且我們知道,在Python中,想要自定義對(duì)象本身的打印輸出結(jié)果的時(shí)候,需要在它的類中實(shí)現(xiàn)__repr__() 方法,例如:

    def __repr__(self):
        return '{}(length={}, width={}, hight={})'.format(
            self.__class__.__name__, self.length, self.width, self.hight)

實(shí)現(xiàn)了__repr__() 方法,當(dāng)我們打印對(duì)象本身的時(shí)候,才會(huì)輸出我們自定義的字符。

box = Box(20, 15, 15)
print(box)
# 結(jié)果輸出為 Box(length=20, width=15, hight=15)

但是有時(shí)會(huì)因?yàn)槁闊?,我們不愿意去?shí)現(xiàn)__repr__()方法,但是不實(shí)現(xiàn)打印結(jié)果又不友好,就陷入了糾結(jié)之中。

如果我么想要實(shí)現(xiàn)對(duì)象比較,有時(shí)候需要判斷2個(gè)對(duì)象是否相等或者比較大小,就要實(shí)現(xiàn)__eq__() 、 __lt__() 、__gt__()等各種方法來實(shí)現(xiàn)對(duì)象之間的比較,例如:

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)

這樣我們又需要實(shí)現(xiàn)這幾個(gè)用于比較的方法。 比如說我們已經(jīng)實(shí)現(xiàn)了上面說過的所有方法,然后又突然添加一個(gè)屬性結(jié)實(shí)度hardness,那么整個(gè)類的方法都需要修改,這是非常折磨人的。 那么有沒有一種方法,可以在創(chuàng)建類的時(shí)候自動(dòng)添加上類似于上面提到的這些東西,答案是有的,那就是我們接下來要介紹的attrs模塊,它可以幫助我們很方便的定義類。

1、attrs的使用

我們可以使用pip install attrs進(jìn)行安裝。

然后將上面的代碼改造一下:

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定義所有的屬性,同時(shí)指定了屬性的類型和默認(rèn)值。而且我們沒有實(shí)現(xiàn)任何一個(gè)上面所提到的方法,但是確實(shí)實(shí)現(xiàn)了所有的功能。 現(xiàn)在如果我們添加一個(gè)屬性顏色color,這個(gè)屬性不參與對(duì)象的比較,但是打印的時(shí)候要輸出,添加一個(gè)屬性結(jié)實(shí)度hardness,這個(gè)屬性參與對(duì)象的比較,但是打印對(duì)象的時(shí)候不輸出,就非常簡單了:

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庫的話,會(huì)讓類的定義變得高效簡潔,就不需要再寫哪些冗余又復(fù)雜的代碼了。 關(guān)于attrib() 接收以下參數(shù):

  • default:屬性的默認(rèn)值,如果沒有傳入初始化數(shù)據(jù),那么就會(huì)使用默認(rèn)值
  • validator:驗(yàn)證器,檢查傳入的參數(shù)是否合法
  • repr:是否參與對(duì)象打印時(shí)的輸出
  • cmp:是否參與對(duì)象比較
  • hash:是否進(jìn)行去重
  • init:是否參與初始化,如果為False,那么這個(gè)參數(shù)不能當(dāng)做類的初始化參數(shù),默認(rèn)是True
  • metadata:元數(shù)據(jù),只讀性的附加數(shù)據(jù)
  • type:類型,比如 int、str 等各種類型,默認(rèn)為 None
  • converter:轉(zhuǎn)換器,進(jìn)行一些值的處理和轉(zhuǎn)換器,增加容錯(cuò)性
  • kw_only:是否為強(qiáng)制關(guān)鍵字參數(shù),默認(rèn)為 False

這里我們只重點(diǎn)說一下驗(yàn)證器和轉(zhuǎn)換器,其他的參數(shù)都很好理解。

2、驗(yàn)證器

有時(shí)候在設(shè)置一個(gè)屬性的時(shí)候必須要滿足某個(gè)條件,比如上面的顏色color屬性,我們使用的是RGB三原色方式,例如黑色是(255,255,255),對(duì)于這種情況,我們就需要驗(yàn)證屬性是否合法。

例如:

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é)果為:

上述代碼中定義了一個(gè)驗(yàn)證器color_is_valid()方法來驗(yàn)證顏色color是否合法,不合法時(shí)就會(huì)拋異常。

驗(yàn)證器方法接收三個(gè)參數(shù):

  • instance:類對(duì)象
  • attr:屬性名
  • value:屬性值

而且attrs模塊也提供了許多內(nèi)置驗(yàn)證器,這里就不做贅述了。

3、轉(zhuǎn)換器

轉(zhuǎn)換器主要做一些值的處理和轉(zhuǎn)換,增加類的容錯(cuò)性,比如一個(gè)屬性接收的是int類型,我們想要的是傳入了數(shù)字字符串也不會(huì)報(bào)錯(cuò),那我們就可以增加轉(zhuǎn)換器,將字符串自動(dòng)轉(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)

上面定義了一個(gè)方法to_int() ,可以將值轉(zhuǎn)化為數(shù)字類型,轉(zhuǎn)換異常就返回None,這樣容錯(cuò)性非常高了。

到此這篇關(guān)于Python attrs提高面向?qū)ο缶幊绦试敿?xì)的文章就介紹到這了,更多相關(guān)Python attrs提高面向?qū)ο缶幊绦蕛?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論