欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python的描述器descriptor詳解

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

基本說明

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

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

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)

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

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

示例Demo1

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

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

下面是使用描述器實(shí)現(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

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

然后,我們定義了一個(gè)Temperature類,它有一個(gè)celsius屬性,它被綁定到Celsius類的實(shí)例上。我們還定義了一個(gè)只讀屬性fahrenheit,它可以通過celsius屬性自動(dòng)計(jì)算得出。

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

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

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

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

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

示例Demo2

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

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

我們可以使用描述器將計(jì)數(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

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

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

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

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

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

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

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

示例Demo3

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

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

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

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")

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

然后,在Person類中,我們定義了一個(gè)名為full_name的屬性,它被綁定到了一個(gè)NameAlias實(shí)例上,用于實(shí)現(xiàn)屬性別名。在Person類的__init__()方法中,我們初始化name屬性的值。現(xiàn)在,我們可以創(chuàng)建一個(gè)Person對(duì)象,并訪問它的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"

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

示例Demo4

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

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

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

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()

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

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

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

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

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

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

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

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

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

相關(guān)文章

  • Python?matplotlib?繪制散點(diǎn)圖詳解建議收藏

    Python?matplotlib?繪制散點(diǎn)圖詳解建議收藏

    在數(shù)據(jù)統(tǒng)計(jì)圖表中,有一種圖表是散列點(diǎn)分布在坐標(biāo)中,反應(yīng)數(shù)據(jù)隨著自變量變化的趨勢。這篇文章主要介紹了如何通過matplotlib繪制散點(diǎn)圖,需要的朋友可以參考一下
    2021-12-12
  • 使用python實(shí)現(xiàn)生成用戶信息

    使用python實(shí)現(xiàn)生成用戶信息

    這篇文章主要介紹了使用python實(shí)現(xiàn)生成用戶信息的相關(guān)代碼,非常的簡單實(shí)用,需要的朋友可以參考下
    2017-03-03
  • python制作簡單五子棋游戲

    python制作簡單五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了python制作簡單五子棋游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • python多重繼承新算法C3介紹

    python多重繼承新算法C3介紹

    這篇文章主要介紹了python多重繼承新算法C3介紹,多重繼承需要復(fù)雜的算法,本文就詳細(xì)講解了新算法C3,需要的朋友可以參考下
    2014-09-09
  • python list使用示例 list中找連續(xù)的數(shù)字

    python list使用示例 list中找連續(xù)的數(shù)字

    這篇文章主要介紹了list中找連續(xù)的數(shù)字的示例,大家參考使用吧
    2014-01-01
  • 在PyTorch中使用標(biāo)簽平滑正則化的問題

    在PyTorch中使用標(biāo)簽平滑正則化的問題

    這篇文章主要介紹了如何在PyTorch中使用標(biāo)簽平滑正則化的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Python?Numpy布爾數(shù)組在數(shù)據(jù)分析中的應(yīng)用小結(jié)

    Python?Numpy布爾數(shù)組在數(shù)據(jù)分析中的應(yīng)用小結(jié)

    本文深入探討了Python的Numpy庫中的布爾數(shù)組功能,介紹了布爾運(yùn)算、布爾索引的使用方法,并通過示例展示了如何在數(shù)據(jù)分析中利用布爾數(shù)組進(jìn)行數(shù)據(jù)篩選和處理,感興趣的朋友一起看看吧
    2024-09-09
  • 基于Python實(shí)現(xiàn)屏幕取色工具

    基于Python實(shí)現(xiàn)屏幕取色工具

    屏幕取色小工具?是一種實(shí)用的軟件工具,主要用于從屏幕上精確獲取顏色值,非常適合設(shè)計(jì)、編程等需要精確配色的領(lǐng)域,下面我們看看如何利用Python編寫一個(gè)屏幕取色工具吧
    2024-12-12
  • 淺析Python中的多進(jìn)程與多線程的使用

    淺析Python中的多進(jìn)程與多線程的使用

    這篇文章主要介紹了Python中的多進(jìn)程與多線程,線程與進(jìn)程一直是Python學(xué)習(xí)和運(yùn)用當(dāng)中的重點(diǎn)和難點(diǎn),本文采用簡單的例子進(jìn)行講解,需要的朋友可以參考下
    2015-04-04
  • Python實(shí)現(xiàn)將DOC文檔轉(zhuǎn)換為PDF的方法

    Python實(shí)現(xiàn)將DOC文檔轉(zhuǎn)換為PDF的方法

    這篇文章主要介紹了Python實(shí)現(xiàn)將DOC文檔轉(zhuǎn)換為PDF的方法,涉及Python調(diào)用系統(tǒng)win32com組件實(shí)現(xiàn)文件格式轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07

最新評(píng)論