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