最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python的描述器descriptor詳解

 更新時間:2023年07月12日 10:02:58   作者:菜鳥小超  
這篇文章主要介紹了python的描述器descriptor詳解,描述器可以用于控制屬性的讀取、寫入和刪除等操作,同時還可以用于實現(xiàn)計算屬性、類屬性、屬性別名等高級功能,需要的朋友可以參考下

基本說明

Python的描述器(descriptor)是一種Python對象,可以通過定義一組特定的方法來管理另一個對象的訪問。描述器可以用于控制屬性的讀取、寫入和刪除等操作,同時還可以用于實現(xiàn)計算屬性、類屬性、屬性別名等高級功能。

在Python中,描述器是通過實現(xiàn)__get__()、__set__()__delete__()方法的對象來定義的。當一個描述器被綁定到一個類的屬性上時,Python會自動將其轉(zhuǎn)化為描述器對象,并在訪問該屬性時調(diào)用對應的描述器方法。

class Descriptor:
    def __get__(self, instance, owner):
        print("Getting the value")
        return self.value
    def __set__(self, instance, value):
        print("Setting the value")
        self.value = value
class MyClass:
    attr = Descriptor()
obj = MyClass()
obj.attr = 42
print(obj.attr)

描述器是一種強大的Python語言特性,可以用于實現(xiàn)各種高級功能,例如:

  1. 計算屬性:描述器可以根據(jù)其他屬性的值動態(tài)計算出一個屬性的值,而不是存儲屬性的值。這可以幫助我們簡化代碼,并且可以在不改變接口的情況下改變屬性的實現(xiàn)方式。
  2. 類屬性:描述器可以讓我們將屬性綁定到類上,而不是綁定到實例上。這可以讓我們在所有實例之間共享屬性值,并且可以在運行時動態(tài)更改屬性的值。
  3. 屬性別名:描述器可以讓我們定義一個屬性的別名,讓一個屬性具有多個名稱。這可以幫助我們簡化代碼,并且可以在不改變接口的情況下更改屬性的名稱。
  4. 數(shù)據(jù)驗證:描述器可以讓我們在設(shè)置屬性值之前驗證輸入數(shù)據(jù),確保它們符合我們的預期格式和類型。這可以提高代碼的健壯性,并且可以幫助我們避免一些常見的錯誤。

示例Demo1

假設(shè)我們有一個Temperature類,用于表示溫度。該類有一個名為celsius的屬性,表示攝氏溫度。我們希望實現(xiàn)以下功能:

  1. 計算屬性fahrenheit,表示華氏溫度,它應該是一個只讀屬性,可以通過攝氏溫度自動計算得出。
  2. 限制celsius屬性的取值范圍在-273.15℃到1000℃之間,如果嘗試設(shè)置超出此范圍的值,應該引發(fā)ValueError異常。

下面是使用描述器實現(xiàn)以上功能的示例代碼:

class Celsius:
    def __init__(self, value=0.0):
        self._value = value
    def __get__(self, instance, owner):
        return self._value
    def __set__(self, instance, value):
        if value < -273.15 or value > 1000.0:
            raise ValueError("Temperature out of range")
        self._value = value
class Temperature:
    celsius = Celsius()
    @property
    def fahrenheit(self):
        return self.celsius * 1.8 + 32

在這個示例中,我們定義了一個Celsius類,它是一個描述器,用于限制Temperature類的celsius屬性的取值范圍。在Celsius類中,我們實現(xiàn)了__get__()__set__()方法,分別在讀取和設(shè)置celsius屬性時被調(diào)用。在__set__()方法中,我們檢查輸入的值是否在允許的范圍內(nèi),如果不是,則引發(fā)一個異常。

然后,我們定義了一個Temperature類,它有一個celsius屬性,它被綁定到Celsius類的實例上。我們還定義了一個只讀屬性fahrenheit,它可以通過celsius屬性自動計算得出。

現(xiàn)在,我們可以創(chuàng)建一個Temperature對象,并設(shè)置其celsius屬性,如下所示:

t = Temperature()
t.celsius = 25.0
print(t.celsius)     # 輸出 25.0
print(t.fahrenheit)  # 輸出 77.0

在這個示例中,我們創(chuàng)建了一個Temperature對象,并將其celsius屬性設(shè)置為25.0。然后,我們打印了celsiusfahrenheit屬性的值,它們分別是25.0和77.0,符合我們預期的結(jié)果。

如果我們嘗試設(shè)置一個超出允許范圍的值,例如-300.0,會引發(fā)一個異常,如下所示:

t.celsius = -300.0  # 引發(fā) ValueError: Temperature out of range

示例Demo2

下面是一個示例,演示如何使用描述器將屬性綁定到類上。

假設(shè)我們有一個名為Counter的類,它用于計數(shù)器操作,可以用于記錄創(chuàng)建的對象數(shù)或者其他類級別的計數(shù)。

我們可以使用描述器將計數(shù)器屬性綁定到Counter類上,如下所示:

class Counter:
    _count = 0
    class CountDescriptor:
        def __get__(self, instance, owner):
            return owner._count
        def __set__(self, instance, value):
            owner = type(instance)
            owner._count = value
    count = CountDescriptor()
    def __init__(self):
        type(self)._count += 1

在這個示例中,我們定義了一個Counter類,它有一個名為count的屬性,它被綁定到了一個內(nèi)部的CountDescriptor描述器類上。

CountDescriptor類中,我們實現(xiàn)了__get__()__set__()方法,它們分別在讀取和設(shè)置count屬性時被調(diào)用。在__get__()方法中,我們返回Counter類的_count屬性的值。在__set__()方法中,我們通過獲取實例的類型(即Counter類),并設(shè)置其_count屬性的值來設(shè)置計數(shù)器的值。

然后,在Counter類的__init__()方法中,我們在創(chuàng)建對象時自動增加計數(shù)器的值。

現(xiàn)在,我們可以創(chuàng)建多個Counter對象,并訪問它們的count屬性,如下所示:

c1 = Counter()
c2 = Counter()
print(c1.count)  # 輸出 2
print(c2.count)  # 輸出 2
Counter.count = 100
print(c1.count)  # 輸出 100
print(c2.count)  # 輸出 100

在這個示例中,我們創(chuàng)建了兩個Counter對象,并分別將它們存儲在c1c2變量中。然后,我們打印它們的count屬性,它們的值都是2,表示我們已經(jīng)創(chuàng)建了兩個Counter對象。

接著,我們將Counter類的count屬性設(shè)置為100,這將改變所有對象的計數(shù)器值。然后,我們再次打印c1c2count屬性,它們的值都變成了100,說明我們成功地將屬性綁定到了類上,實現(xiàn)了所有實例之間共享屬性值的效果。

示例Demo3

下面是一個示例,演示如何使用描述器實現(xiàn)屬性別名。

假設(shè)我們有一個Person類,它有一個名為name的屬性,表示人的名字。現(xiàn)在我們想要為name屬性定義一個別名,叫做full_name,以便在某些情況下,我們可以使用full_name屬性來代替name屬性。

我們可以使用描述器來實現(xiàn)這個功能,如下所示:

class NameAlias:
    def __init__(self, name):
        self.name = name
    def __get__(self, instance, owner):
        return getattr(instance, self.name)
    def __set__(self, instance, value):
        setattr(instance, self.name, value)
class Person:
    def __init__(self, name):
        self.name = name
    full_name = NameAlias("name")

在這個示例中,我們定義了一個NameAlias描述器類,它用于實現(xiàn)屬性別名功能。在NameAlias類中,我們實現(xiàn)了__get__()__set__()方法,它們分別在讀取和設(shè)置full_name屬性時被調(diào)用。在__get__()方法中,我們使用getattr()函數(shù)獲取對象的name屬性值,并返回它。在__set__()方法中,我們使用setattr()函數(shù)設(shè)置對象的name屬性值為傳入的值。

然后,在Person類中,我們定義了一個名為full_name的屬性,它被綁定到了一個NameAlias實例上,用于實現(xiàn)屬性別名。在Person類的__init__()方法中,我們初始化name屬性的值。現(xiàn)在,我們可以創(chuàng)建一個Person對象,并訪問它的namefull_name屬性,如下所示:

p = Person("Alice")
print(p.name)       # 輸出 "Alice"
print(p.full_name)  # 輸出 "Alice"
p.full_name = "Bob"
print(p.name)       # 輸出 "Bob"
print(p.full_name)  # 輸出 "Bob"

在這個示例中,我們創(chuàng)建了一個Person對象,并將其存儲在p變量中。然后,我們打印它的namefull_name屬性,它們的值都是"Alice",表示它們是等價的。接著,我們將pfull_name屬性設(shè)置為"Bob",這將同時改變name屬性的值。然后,我們再次打印namefull_name屬性,它們的值都是"Bob",說明我們成功地實現(xiàn)了屬性別名的功能。

示例Demo4

下面是一個示例,演示如何使用描述器實現(xiàn)數(shù)據(jù)驗證功能。

假設(shè)我們有一個Person類,它有一個名為age的屬性,表示人的年齡?,F(xiàn)在我們想要對age屬性的輸入數(shù)據(jù)進行驗證,以確保它的值在0到150之間。

我們可以使用描述器來實現(xiàn)這個功能,如下所示:

class AgeValidator:
    def __get__(self, instance, owner):
        return instance._age
    def __set__(self, instance, value):
        if not isinstance(value, int) or value < 0 or value > 150:
            raise ValueError("Invalid age")
        instance._age = value
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    age = AgeValidator()

在這個示例中,我們定義了一個AgeValidator描述器類,它用于實現(xiàn)數(shù)據(jù)驗證功能。在AgeValidator類中,我們實現(xiàn)了__get__()__set__()方法,它們分別在讀取和設(shè)置age屬性時被調(diào)用。在__set__()方法中,我們首先檢查輸入的值是否是整數(shù),并且是否在0到150之間。如果輸入數(shù)據(jù)不符合要求,我們將引發(fā)一個ValueError異常。否則,我們將設(shè)置instance._age屬性的值為傳入的值。

然后,在Person類中,我們定義了一個名為age的屬性,它被綁定到了一個AgeValidator實例上,用于實現(xiàn)數(shù)據(jù)驗證功能。在Person類的__init__()方法中,我們初始化nameage屬性的值?,F(xiàn)在,我們可以創(chuàng)建一個Person對象,并嘗試設(shè)置其age屬性的值,如下所示:

p = Person("Alice", 25)
print(p.age)  # 輸出 25
p.age = 200  # 引發(fā) ValueError: Invalid age

在這個示例中,我們創(chuàng)建了一個Person對象,并將其存儲在p變量中。然后,我們打印它的age屬性,它的值是25。接著,我們嘗試將page屬性設(shè)置為200,這將引發(fā)一個ValueError異常,因為200超出了允許的范圍。這說明我們成功地使用描述器實現(xiàn)了數(shù)據(jù)驗證功能,可以避免一些常見的錯誤。

在這個示例中,Person類中有兩個名為age的定義,一個是在__init__()方法中進行初始化的實例屬性,另一個是通過描述器AgeValidator綁定到Person類上的類屬性。

當我們在__init__()方法中設(shè)置self.age = age時,它實際上是在創(chuàng)建一個實例屬性,而不是類屬性。這個實例屬性只對當前對象有效,而不對所有Person對象都有效。

而當我們在Person類中定義了一個名為age的描述器屬性時,它實際上是在創(chuàng)建一個類屬性,這個屬性可以被所有Person對象所共享,它定義了age屬性的讀寫行為,可以對屬性值進行驗證,保證數(shù)據(jù)的正確性。

因此,這兩個age屬性雖然名字相同,但它們的作用范圍和用途不同。實例屬性是用來存儲每個對象的不同數(shù)據(jù),而類屬性則是用來實現(xiàn)屬性的共享和控制。描述器可以讓我們將類屬性綁定到一個自定義的屬性讀寫行為上,從而實現(xiàn)更靈活的屬性操作。

到此這篇關(guān)于python的描述器descriptor詳解的文章就介紹到這了,更多相關(guān)python的描述器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

梓潼县| 乌拉特前旗| 区。| 岑溪市| 抚顺市| 古蔺县| 平果县| 治多县| 汝城县| 星子县| 昔阳县| 麻栗坡县| 寿光市| 盘山县| 苍溪县| 教育| 石家庄市| 江津市| 扬中市| 宁德市| 嘉鱼县| 余江县| 南阳市| 上高县| 保康县| 外汇| 新建县| 延津县| 尖扎县| 攀枝花市| 达孜县| 石狮市| 礼泉县| 奉新县| 永善县| 嵊州市| 乡宁县| 云阳县| 桓台县| 南皮县| 梁平县|