一文帶你搞懂Python中的描述符(Descriptor)
一、什么是描述符?
在Python中,描述符是一個(gè)實(shí)現(xiàn)了特定協(xié)議的對(duì)象。這個(gè)協(xié)議包括__get__()、__set__()和__delete__()方法。描述符使我們可以在訪問(wèn)、設(shè)置或刪除屬性時(shí)定義額外的行為。
描述符主要用于管理對(duì)特定屬性的訪問(wèn)。當(dāng)你在類中定義了一個(gè)描述符,Python會(huì)在你訪問(wèn)該屬性時(shí)使用描述符中定義的行為,而不是直接訪問(wèn)對(duì)象的字典。
讓我們看一個(gè)簡(jiǎn)單的例子,一個(gè)只讀的描述符:
class ReadOnly:
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
return self.val
def __set__(self, obj, val):
raise AttributeError(f"{self.name} is read-only")
class MyClass:
attr = ReadOnly(10, 'attr')在這個(gè)例子中,ReadOnly是一個(gè)描述符。當(dāng)我們嘗試設(shè)置MyClass的attr屬性時(shí),它會(huì)拋出一個(gè)AttributeError,因?yàn)?code>attr是只讀的。
二、描述符的類型
在Python中,有兩種類型的描述符:數(shù)據(jù)描述符和非數(shù)據(jù)描述符。
數(shù)據(jù)描述符是定義了__set__()或__delete__()方法的描述符。當(dāng)一個(gè)數(shù)據(jù)描述符和一個(gè)實(shí)例字典中的項(xiàng)有相同的名字時(shí),數(shù)據(jù)描述符將具有更高的優(yōu)先級(jí)。
非數(shù)據(jù)描述符只定義了__get__()方法。如果實(shí)例字典中有相同名字的項(xiàng),那么這個(gè)項(xiàng)將具有更高的優(yōu)先級(jí)。
三、使用描述符
描述符通常用于實(shí)現(xiàn)高級(jí)功能,例如數(shù)據(jù)驗(yàn)證、屬性訪問(wèn)日志記錄、類型檢查等。下面我們將實(shí)現(xiàn)一個(gè)簡(jiǎn)單的類型檢查描述符:
class Typed:
def __init__(self, name, required_type):
self.name = name
self.required_type = required_type
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, self.required_type):
raise TypeError(f"Expected {self.required_type}")
instance.__dict__[self.name] = value
class MyClass:
attr = Typed('attr', int)在這個(gè)例子中,Typed描述符確保attr屬性總是一個(gè)整數(shù)。如果我們嘗試設(shè)置一個(gè)非整數(shù)值,就會(huì)拋出一個(gè)TypeError。
總的來(lái)說(shuō),描述符提供了一種優(yōu)雅而強(qiáng)大的方式來(lái)管理對(duì)象的屬性。它們?yōu)閿?shù)據(jù)封裝、自定義數(shù)據(jù)類型、屬性驗(yàn)證和計(jì)算屬性提供了無(wú)盡的可能性。理解和使用描述符可以幫助我們寫(xiě)出更清晰、更靈活和更健壯的代碼。
以下是如何使用這個(gè)Typed描述符的例子:
my_obj = MyClass()
my_obj.attr = 10
print(my_obj.attr) # Output: 10
try:
my_obj.attr = 'hello'
except TypeError as e:
print(e) # Output: Expected <class 'int'>在這個(gè)例子中,你可以看到當(dāng)我們?cè)噲D給attr賦值一個(gè)非整數(shù)值時(shí),描述符會(huì)引發(fā)一個(gè)TypeError。
描述符不僅可以用于類型檢查,還可以用于許多其他有用的功能,例如數(shù)據(jù)綁定、讀寫(xiě)權(quán)限控制、自動(dòng)更新屬性值等。當(dāng)你需要在獲取、設(shè)置或刪除屬性時(shí)執(zhí)行特定的操作時(shí),描述符可能會(huì)是一個(gè)很好的選擇。
四、描述符的高級(jí)用法
描述符的常見(jiàn)用法是實(shí)現(xiàn)屬性的數(shù)據(jù)綁定和數(shù)據(jù)驗(yàn)證。然而,描述符還有一些高級(jí)的用法,例如延遲計(jì)算和函數(shù)重載。以下是一個(gè)使用描述符實(shí)現(xiàn)延遲計(jì)算的例子:
class LazyProperty:
def __init__(self, function):
self.function = function
self.name = function.__name__
def __get__(self, obj, objtype=None):
if obj is None:
return self
value = self.function(obj)
setattr(obj, self.name, value)
return value
class MyClass:
@LazyProperty
def expensive_computation(self):
print("Computing...")
return sum(range(1000000))
my_instance = MyClass()
print(my_instance.expensive_computation) # Output: Computing... 499999500000
print(my_instance.expensive_computation) # Output: 499999500000在這個(gè)例子中,expensive_computation屬性在第一次訪問(wèn)時(shí)執(zhí)行一次昂貴的計(jì)算,之后的訪問(wèn)會(huì)直接返回已經(jīng)計(jì)算出的結(jié)果。
五、描述符的局限性
雖然描述符是一個(gè)強(qiáng)大的特性,但它也有一些局限性。首先,描述符只能在新式類中使用。另外,描述符的行為依賴于其在類中的定義順序,這有時(shí)可能會(huì)導(dǎo)致意料之外的結(jié)果。最后,描述符對(duì)類屬性的管理是全局的,無(wú)法針對(duì)單個(gè)實(shí)例進(jìn)行定制。
盡管有這些局限性,描述符仍然是Python中一個(gè)非常有用的工具。通過(guò)理解和利用描述符,我們可以編寫(xiě)出更安全、更靈活的代碼。
希望這篇文章能幫助你理解Python中的描述符,以及如何使用它們來(lái)提高代碼的質(zhì)量和靈活性。
以上就是一文帶你搞懂Python中的描述符(Descriptor)的詳細(xì)內(nèi)容,更多關(guān)于Python 描述符的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
更換pip國(guó)內(nèi)鏡像源提升Python包下載速度的配置方法
作為一名Python開(kāi)發(fā)者,你一定遇到過(guò)這樣的場(chǎng)景:深夜加班時(shí),一個(gè)簡(jiǎn)單的pip install命令卻卡在Downloading…界面,進(jìn)度條慢如蝸牛,這不是你的網(wǎng)絡(luò)問(wèn)題,而是默認(rèn)的PyPI服務(wù)器位于海外,本文將手把手教你如何配置國(guó)內(nèi)鏡像源,需要的朋友可以參考下2026-01-01
Python 安裝第三方庫(kù) pip install 安裝慢安裝不上的解決辦法
很多朋友反映在使用pip install安裝python 第三方庫(kù)的過(guò)程中會(huì)出現(xiàn)網(wǎng)速很慢,或者是安裝下載到中途,停止,卡主,或者是下載報(bào)錯(cuò)等問(wèn)題,下面小編給大家?guī)?lái)了解決方法,一起看看吧2019-06-06
Django JWT Token RestfulAPI用戶認(rèn)證詳解
這篇文章主要介紹了Django JWT Token RestfulAPI用戶認(rèn)證詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
PyCharm安裝配置Qt Designer+PyUIC圖文教程
這篇文章主要介紹了PyCharm安裝配置Qt Designer+PyUIC圖文教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
Python二進(jìn)制轉(zhuǎn)化為十進(jìn)制數(shù)學(xué)算法詳解
這篇文章主要介紹了Python二進(jìn)制轉(zhuǎn)化為十進(jìn)制數(shù)學(xué)算法,同時(shí)在這里也給大家分享一個(gè)好用的內(nèi)置函數(shù)map(),需要的朋友可以參考下2023-01-01

