描述符(Descriptors)是Python語言中一個深奧但卻重要的一部分。它們廣泛應(yīng)用于Python語言的內(nèi)核,熟練掌握描述符將會為Python程序員的工具箱添加一個額外的技巧。為了給接下來對描述符的討論做一些鋪墊,我將描述一些程序員可能會在日常編程活動中遇到的場景,然后我將解釋描述符是什么,以及它們?nèi)绾螢檫@些場景提供優(yōu)雅的解決方案。在這篇總結(jié)中,我會使用新樣式類來指代Python版本。
1、假設(shè)一個程序中,我們需要對一個對象屬性執(zhí)行嚴(yán)格的類型檢查。然而,Python是一種動態(tài)語言,所以并不支持類型檢查,但是這并不妨礙我們實現(xiàn)自己版本,且較為初級的類型檢查。對象屬性類型檢查的傳統(tǒng)方法可能采用下面的方式:
def __init__(self, name, age): if isinstance(str, name): self.name = name else: raise TypeError("Must be a string") if isinstance(int, age): self.age = age else: raise TypeError("Must be an int")上面是執(zhí)行這種類型檢查的一種方法,但是參數(shù)數(shù)量增加時它將變得比較繁瑣。另外,在賦值之前,我們可以創(chuàng)建一個在__init__中調(diào)用的type_check(type, val)函數(shù),但是當(dāng)我們想在其他地方設(shè)置屬性值時,該如何簡單地實現(xiàn)這種檢查呢。我想到的一個快速解決方案是Java中的getters和setters,但是這并不符合Python風(fēng)格,并且比較麻煩。
2、假設(shè)在一個程序中,我們想創(chuàng)建一些在運行時立刻初始化然后變成只讀的屬性。有人也能想到利用Python中的特殊方法來實現(xiàn),但這種實現(xiàn)方法仍舊是笨拙和繁瑣的。
3、最后,設(shè)想一個程序中,我們希望以某種方式自定義對象屬性的訪問。例如需要記錄這種屬性的訪問。同樣的,還是可以想到一個解決方法,即使這種解決方案可能比較笨重并且不可復(fù)用。
上述問題因都與屬性引用相關(guān)而全部聯(lián)系在了一起。下面,我們將嘗試自定義屬性的訪問方法。
Python描述符
針對上面所列的問題,描述符提供了優(yōu)雅、簡潔、健壯和可重用的解決方案。簡而言之,一個描述符就是一個對象,該對象代表了一個屬性的值。這就意味著如果一個賬戶對象有一個屬性“name”,那么描述符就是另一個能夠用來代表屬性“name”持有值的對象。描述符協(xié)議中“定義了__get__”、“__set__”或”__delete__” 這些特殊方法,描述符是實現(xiàn)其中一個或多個方法的對象。這些方法中每一種方法的簽名如下所示:
python descr.get(self,obj,type=None)->value。 descr.__set__(self, obj, value) --> None descr.__delete__(self, obj) --> None
實現(xiàn)__get__方法的對象是非數(shù)據(jù)描述符,意味著在初始化之后它們只能被讀取。而同時實現(xiàn)__get__和__set__的對象是數(shù)據(jù)描述符,意味著這種屬性是可寫的。
新聞熱點
疑難解答
圖片精選