摘要:下面我們用描述符來實現中的動態屬性和特性中提及的訂單結算代碼第四版使用描述符實現訂單結算功能描述符基于協議實現,無需創建子類。特性是覆蓋型描述符。非覆蓋型描述符沒有實現方法的描述符屬于非覆蓋型描述符。類中定義的方法是非覆蓋型描述符。
導語:本文章記錄了本人在學習Python基礎之元編程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。
本文重點:
1、了解描述符的定義,功能,協議和用法;一、描述符
2、了解覆蓋型描述符和非覆蓋型描述符的概念和區別;
3、了解描述符的用法建議。
描述符:是實現了特定協議的類。
描述符功能:是對多個屬性運用相同存取邏輯的一種方式。
描述符協議:包括__get__、__set__、和__delete__方法。通常只實現部分協議。大多數描述符只實現了__get__和__set__方法,但是property類實現了完整的描述符協議。
下面我們用描述符來實現Python中的動態屬性和特性中提及的訂單結算代碼:
第四版:使用描述符實現訂單結算功能
class Quantity:#描述符基于協議實現,無需創建子類。 def __init__(self,storage_name): self.storage_name=storage_name#storage_name是托管實例中存儲值的屬性的名稱。 def __set__(self, instance, value):#重要!instance是LineItem實例,self是描述符實例。 if value > 0: instance.__dict__[self.storage_name]=value#此處必須直接存入__dict__,否則使用setattr函數會導致無限遞歸。 else: raise ValueError("Value must be > 0") class LineItem: weight = Quantity("weight")#將描述符實例綁定到weight屬性。 price = Quantity("price")#同上。 def __init__(self,description,weight,price): self.description=description self.weight=weight self.price=price def subtotal(self): return self.weight*self.price
小結:描述符類的實例能用作托管類的屬性,這一點很重要!
不過在上文中的托管類定義體中,實例化描述符如果能按照weight = Quantity()這種格式聲明就更好了。為此我們需要寫一版自動獲取存取屬性名稱的代碼。
第五版:改進描述符類——自動獲取存取屬性名稱
class Quantity:#改進版描述符類 __counter = 0 def __init__(self): cls = self.__class__ prefix = cls.__name__ index = cls.__counter self.storage_name = "_{}#{}".format(prefix, index) #每個描述符實例的屬性名稱都是獨一無二的。 cls.__counter += 1 def __get__(self, instance, owner): #此處owner參數是托管類LineItem。 return getattr(instance, self.storage_name) #從instance中獲取儲存屬性的值。 def __set__(self, instance, value): if value > 0: setattr(instance, self.storage_name, value) #使用setattr把值儲存在instance中。 else: raise ValueError("value must be > 0") class LineItem:#托管類 weight = Quantity() price = Quantity() def __init__(self,description,weight,price): self.description=description self.weight=weight self.price=price def subtotal(self): return self.weight*self.price
Tips:通常,我們不會在使用描述符的模塊中定義描述符,而是在一個多帶帶的實用工具模塊中定義,以便在整個應用中使用。
二、特性工廠函數與描述符類比較我們在Python中的動態屬性和特性中提到過,抽象定義特性的方式有兩種,一是使用特性工廠函數,二是使用描述符類。
現在來對兩種方式的優點進行對比辨析:
特性工廠函數:模式簡單。
描述符類:模式可拓展。可通過子類共享代碼,構建具有部分相同功能的專用描述符,應用更廣泛。
個人建議:當兩種模式均能實現目標時,推薦使用描述類。
三、覆蓋型描述符與非覆蓋型描述符對比覆蓋型描述符:實現__set__方法的描述符屬于覆蓋型描述符。
特性是覆蓋型描述符。
非覆蓋型描述符:沒有實現__set__方法的描述符屬于非覆蓋型描述符。
類中定義的方法是非覆蓋型描述符。
小結:如果設置了同名實例屬性,對于非覆蓋型描述符而言會被覆蓋;對于沒有實現__get__方法的覆蓋型描述符而言,在讀操作時描述符對象也會被覆蓋。
使用特性以保持簡單:創建只讀屬性最簡單的方式是使用特性。
只讀描述符必須有__set__方法:只讀描述符必須定義__get__和__set__兩個方法,只讀屬性的__set__方法只需拋出AttributeError異常,并提供合適的錯誤信息。
用于驗證的描述符可以只有__set__方法:描述符用于驗證屬性時可以不實現__get__,這樣從實例中讀取同名屬性的速度很快。
僅有__get__方法的描述符可以實現高效緩存。
非特殊的方法可以被實例屬性覆蓋。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41477.html
摘要:之所以是這樣是因為當訪問一個實例描述符對象時,會將轉換為。而類的字典中則有描述符對象。這主要就是因為描述符優先。此外,非數據描述符的優先級低于實例屬性。參考以上就是本人對描述符的一些理解,有什么不正確的地方還請不吝指出,謝謝 什么是描述符 python描述符是一個綁定行為的對象屬性,在描述符協議中,它可以通過方法重寫屬性的訪問。這些方法有 __get__(), __set__(), 和...
摘要:不像其他屬性,描述符在類級別上創建。當所有者類被定義時,每個描述符對象都是被綁定到一個不同的類級別屬性的描述符類實例。這必須返回描述符的值。此外,描述符對有一個方便的響應和請求格式。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __getattribute__()方法 __getattribute__()方法是...
摘要:解答三個問題,描述是什么如何實現使用場景一什么是描述符描述符就是一個具有綁定行為的對象屬性,其屬性訪問將由描述符協議中的方法覆蓋。如果這些方法中的任何一個針對某個對象定義,那么它就被認為是一個描述符。 解答三個問題,描述是什么?如何實現?使用場景? 一、什么是描述符 描述符就是一個具有綁定行為的對象屬性,其屬性訪問將由描述符協議中的方法覆蓋。這些方法為 __get__、__set__ ...
閱讀 1122·2021-09-22 15:32
閱讀 1722·2019-08-30 15:53
閱讀 3253·2019-08-30 15:53
閱讀 1404·2019-08-30 15:43
閱讀 453·2019-08-28 18:28
閱讀 2567·2019-08-26 18:18
閱讀 668·2019-08-26 13:58
閱讀 2528·2019-08-26 12:10