在日常的編碼中,我們應(yīng)該使用 Python 的描述符,來(lái)使代碼更具有單一職責(zé)原則,也就是 SRP(Single Responsibility Principle)原則,如果你還沒(méi)有用過(guò)描述符,那快來(lái)看看怎么用吧,不然就不好意思說(shuō)自己懂 Python。
那么什么是描述符?
描述符是控制對(duì)象屬性訪問(wèn)的一種方式。它的好處是,讓我們把類中設(shè)置和檢索屬性的任務(wù)抽離出來(lái),并將這一任務(wù)交給另一個(gè)只有一個(gè)目的的類,幫助我們遵循 SRP 原則,也讓代碼更 Pythonic。
讓我給你舉個(gè)例子。你們大多數(shù)人都會(huì)知道 @property 裝飾器,它基本上與描述符的作用相同?,F(xiàn)在,讓我們編寫一個(gè)驗(yàn)證汽車油箱容量的類:
在上面的代碼示例中,定義了一個(gè)有油箱的汽車類,我們希望限制油箱的容量不能小于 0 或高于 60 升。
@fuel_amount.setter 對(duì)賦值做檢查,如果小于 0 或大于 60,就會(huì)引發(fā) ValueError。為了獲取油箱的容量,我們使用 @property,從私有屬性 _fuel_amount 返回。
這看起來(lái)簡(jiǎn)單,好像也沒(méi)什么問(wèn)題,不過(guò)你細(xì)品一下,就會(huì)發(fā)現(xiàn)當(dāng)屬性越來(lái)越多的時(shí)候,你會(huì)看到滿天的 property 和一堆業(yè)務(wù)邏輯代碼的 setter,最后就是一個(gè)非常臃腫的 Car 類,看到你想吐,這與 Python 的設(shè)計(jì)哲學(xué)簡(jiǎn)單優(yōu)雅相去甚遠(yuǎn)。
幸運(yùn)的是,Python 有描述符。
現(xiàn)在來(lái)看看下面使用了描述符的代碼,是不是清爽了很多:
這里的類 SixtyLitresCapacity 就是一個(gè)描述符類,作用就是限制大小為 0 到 60,具體代碼如下:
其實(shí)也很簡(jiǎn)單,一個(gè)類定義了一個(gè) ??__get__?
?? 和 ??__set__?
? 方法,就可以作為一個(gè)描述符類(還要注意參數(shù)列表)。
需要注意的是,只有為類屬性設(shè)置描述符時(shí)才有效。如果將描述符用于實(shí)例屬性,Python 會(huì)忽略它。
我們還可以做的更好,比如說(shuō)將描述符類做得更加通用:
這里的描述符類 IsBetween 代碼如下:
在 IsBetween 里,我們添加了一些新東西。
1、添加了__init__方法,以啟用上下邊界的初始化(min_value 和 max_value),這樣,不僅可以有 60 升的油箱,還可以在油箱只剩下 5 升燃料時(shí)發(fā)出告警的功能。為了拋出不同的異常,將異常通過(guò)__init__方法的參數(shù)傳進(jìn)去。
2、添加了__set_name__(self, owner, name)方法。因?yàn)樗接袑傩圆灰欢ㄊ莀fuel_amount,可以是你喜歡的任何屬性。這種個(gè)方法打開了將屬性名傳遞給給描述符類的大門。沒(méi)有這個(gè)方法,描述符將無(wú)法從類中獲得任何信息。
可以看到,IsBetween 這個(gè)描述符類更加通用,可以描述諸如電池電量、年齡屬性、溫度等屬性。
你看,描述符類是不是非常有用?同時(shí)也幫助我們的代碼遵循 SRP。
最后的話
本文分享了 Python 中描述符的使用,有沒(méi)有學(xué)到新技能呢?如果覺(jué)得文章有幫助的話,不妨點(diǎn)贊、關(guān)注,你的支持就是最大的鼓勵(lì)。留言討論
掃碼關(guān)注
本文摘自 :https://blog.51cto.com/u