国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁 > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

Python:描述符協(xié)議

0
分享至

在 Python 面向?qū)ο缶幊讨校悓傩缘脑L問和控制非常靈活。為了支持屬性的動(dòng)態(tài)訪問、驗(yàn)證、緩存和代理行為,Python 提供了描述符協(xié)議(Descriptor Protocol),是 Python 中實(shí)現(xiàn)訪問控制、延遲加載、ORM 字段、property 裝飾器等機(jī)制的核心基礎(chǔ)。

描述符提供了比傳統(tǒng) getter/setter 更統(tǒng)一、更強(qiáng)大的能力,是 Python 對(duì)象模型中最重要的機(jī)制之一。理解描述符,能夠讓你真正掌握 Python 的屬性訪問機(jī)制。

一、傳統(tǒng)的 Setter/Getter/Deleter

假設(shè)我們有一個(gè)類 BankAccount,希望控制銀行賬戶余額 _balance 的訪問方式:

        del self._balance

使用方式:

# account.set_balance(-50)              # 會(huì)拋出 ValueError

為什么說這是“傳統(tǒng)的”?

? 必須顯式調(diào)用 get_x / set_x,不夠 Pythonic。

? 無法用自然的屬性語法(obj.attr)。

? 冗長、繁瑣,不符合“簡單即美”的 Python 哲學(xué)。

因此,Python 提供了更高級(jí)的方案 —— @property。

二、Python 的進(jìn)化:@property 裝飾器

@property 允許你用屬性語法訪問方法:

        del self._balance

使用方式:

del account.balance                # 輸出:Deleting balance!

我們也可以不使用裝飾器語法,而是顯式創(chuàng)建 property:

    balance = property(get_balance, set_balance, del_balance)

裝飾器是語法糖,本質(zhì)和顯式寫法等價(jià)!

三、描述符與描述符協(xié)議

property 不是魔法,它基于描述符協(xié)議(Descriptor Protocol)。

(1)什么是描述符

只要一個(gè)對(duì)象實(shí)現(xiàn)了以下任意方法,它就是描述符:

? __get__(self, instance, owner)

? __set__(self, instance, value)

? __delete__(self, instance)

并且當(dāng)此對(duì)象作為類屬性存在時(shí),通過 obj.attr 訪問會(huì)自動(dòng)調(diào)用這些方法。描述符允許我們“鉤住”屬性訪問過程,自定義其行為。

(2)描述符協(xié)議三方法

__get__(self, instance, owner)

讀取屬性時(shí)觸發(fā)。

參數(shù):

self:描述符實(shí)例本身。

instance:通過實(shí)例訪問時(shí)為實(shí)例,通過類訪問時(shí)為 None。

owner:擁有描述符的類(通過類訪問時(shí))。

__set__(self, instance, value)

設(shè)置屬性時(shí)觸發(fā)。

__delete__(self, instance)

刪除屬性時(shí)觸發(fā)。

所有 property、方法綁定、ORM 字段、cached_property 都基于描述符協(xié)議。

(3)property 與描述符的關(guān)系

當(dāng)我們使用 @property 時(shí),本質(zhì)上是在創(chuàng)建一個(gè) property 描述符實(shí)例。

以下是 property 的簡化原理:

        self.fdel(instance)

property 就是一個(gè)實(shí)現(xiàn)了完整描述符協(xié)議的類。

property 默認(rèn)是“非數(shù)據(jù)描述符”;只有在定義了 fset 或 fdel 時(shí)才成為“數(shù)據(jù)描述符”。

四、數(shù)據(jù)描述符與非數(shù)據(jù)描述符

Python 將描述符分為兩類,它們的優(yōu)先級(jí)不同。

(1)數(shù)據(jù)描述符(Data Descriptor)

指的是定義了 __set__ 或 __delete__ 的描述符。

如:

? property(具有 setter 或 deleter)

? 自定義描述符實(shí)現(xiàn)了 __set__

? ORM 字段、typed 屬性驗(yàn)證描述符

優(yōu)先級(jí):數(shù)據(jù)描述符優(yōu)先于實(shí)例屬性。

示例:

print(a.x)   # get   —— 實(shí)例屬性不會(huì)覆蓋數(shù)據(jù)描述符

(2)非數(shù)據(jù)描述符(Non-Data Descriptor)

指的是只實(shí)現(xiàn)了 __get__ 的描述符。

如:

? 普通方法(function)

? property(無 setter / deleter)

優(yōu)先級(jí):實(shí)例屬性優(yōu)先于非數(shù)據(jù)描述符。

示例:

print(a.x)  # 100  —— 實(shí)例字典覆蓋了非數(shù)據(jù)描述符

優(yōu)先級(jí)總結(jié):

數(shù)據(jù)描述符 > 實(shí)例屬性 > 非數(shù)據(jù)描述符 > 普通類屬性

示例:

print(obj.non_data_desc)       # 輸出: "實(shí)例屬性"(實(shí)例屬性優(yōu)先)

五、屬性查找順序

當(dāng)執(zhí)行 obj.attr 時(shí),Python 實(shí)際執(zhí)行(簡化邏輯):

1、在類(type(obj)) 中查找 attr;如果找到且是數(shù)據(jù)描述符 → 調(diào)用其 __get__ 并返回結(jié)果。

2、否則查找實(shí)例字典 obj.__dict__;如果存在 → 返回該值。

3、若類屬性是非數(shù)據(jù)描述符 → 調(diào)用其 __get__ 并返回結(jié)果。

4、否則返回類屬性本身。

5、若都找不到 → 如果對(duì)象實(shí)現(xiàn)了 __getattr__ 則調(diào)用它。

設(shè)置屬性時(shí):

? 若存在數(shù)據(jù)描述符 → 調(diào)用其 __set__

? 否則寫入實(shí)例字典

刪除屬性時(shí):

? 若存在數(shù)據(jù)描述符 → 調(diào)用其 __delete__

? 否則從實(shí)例字典刪除

示例:完整的查找規(guī)則演示

print(demo.class_attr)  # 類屬性

這種精細(xì)的屬性查找順序與描述符優(yōu)先級(jí)機(jī)制,使得 Python 在實(shí)現(xiàn)面向?qū)ο筇匦詴r(shí)既靈活又高效。

六、自定義描述符

下面構(gòu)造一個(gè)完整的年齡驗(yàn)證描述符,改進(jìn) __get__ 的容錯(cuò)處理,同時(shí)演示推薦的實(shí)例數(shù)據(jù)存儲(chǔ)方式(使用實(shí)例字典并帶上唯一鍵)并加入 __set_name__ 支持以獲取屬性名:

將其綁定到類屬性:

使用示例:

(1)描述符實(shí)例是類屬性,不是實(shí)例屬性

描述符對(duì)象只創(chuàng)建一次(在類定義時(shí)),不應(yīng)該在描述符內(nèi)部用 self.xxx 來存儲(chǔ)每個(gè)實(shí)例的數(shù)據(jù),否則所有實(shí)例會(huì)共享同一份數(shù)據(jù)(通常這是錯(cuò)誤的)。正確做法是將實(shí)例數(shù)據(jù)存儲(chǔ)在 instance.__dict__ 或使用 instance 上的獨(dú)立鍵(例如 _{name})。

(2)set_name(推薦)

自 Python 3.6 起,描述符可以實(shí)現(xiàn) __set_name__(self, owner, name),類創(chuàng)建時(shí)會(huì)被調(diào)用一次,這可以幫助描述符自動(dòng)記錄它在類中對(duì)應(yīng)的屬性名,從而簡化向 instance.__dict__ 中存儲(chǔ)值的實(shí)現(xiàn)(見上面示例)。這是實(shí)現(xiàn)“按屬性名存儲(chǔ)”“不會(huì)沖突”的推薦方式。

(3)刪除屬性后再訪問

del p.age 會(huì)調(diào)用 __delete__,如果我們?cè)?__get__ 中直接訪問 instance.__dict__ 中的鍵而該鍵不存在,會(huì)拋出 AttributeError。在實(shí)際實(shí)現(xiàn)中可以選擇更友好的行為(例如返回 None、拋出帶信息的異常或觸發(fā)延遲加載)。

七、描述符的典型應(yīng)用場景

描述符在 Python 中有廣泛的應(yīng)用。

(1)數(shù)據(jù)驗(yàn)證與類型檢查

(2)延遲加載與緩存機(jī)制(如 cached_property)

(3)觀察者模式與屬性監(jiān)聽

(4)權(quán)限控制與訪問審計(jì)

(5)ORM 與數(shù)據(jù)映射(字段描述符)

(6)配置管理與依賴注入

補(bǔ)充說明:方法如何綁定為 bound method

Python 中的函數(shù)對(duì)象(定義在類體中的函數(shù))實(shí)現(xiàn)了 __get__(即函數(shù)對(duì)象是非數(shù)據(jù)描述符),當(dāng)通過實(shí)例訪問時(shí),function.__get__(instance, owner) 會(huì)返回一個(gè)“綁定方法”(bound method),它把該實(shí)例作為第一個(gè)參數(shù)(self)封裝到函數(shù)上。理解這一點(diǎn)有助于把“方法也是描述符”與前面描述符優(yōu)先級(jí)的討論連起來。

小結(jié)

描述符協(xié)議是 Python 中控制屬性訪問的底層機(jī)制。只要一個(gè)類實(shí)現(xiàn)了 __get__、__set__ 或 __delete__,它就能作為描述符攔截屬性的讀取、寫入和刪除操作。property、方法綁定、ORM 字段以及許多高級(jí)特性都依賴描述符協(xié)議。

理解描述符的關(guān)鍵在于區(qū)分?jǐn)?shù)據(jù)描述符和非數(shù)據(jù)描述符,并掌握它們?cè)趯傩圆檎翼樞蛑械牟煌瑑?yōu)先級(jí)。__set_name__ 是現(xiàn)代描述符實(shí)現(xiàn)中非常有用的鉤子(Python 3.6+),推薦在自定義描述符中使用它來管理實(shí)例字典的鍵。

通過自定義描述符,我們可以構(gòu)建高度可復(fù)用、可擴(kuò)展的屬性管理邏輯,使得類的行為更加靈活與優(yōu)雅;描述符不僅是 Python 的底層機(jī)制,更是構(gòu)建大型系統(tǒng)與框架的基礎(chǔ)組件。


點(diǎn)贊有美意,贊賞是鼓勵(lì)

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
皇馬丟冠!神奇3分鐘3球,10人巴薩3:2加冕,姆巴佩難救阿隆索!

皇馬丟冠!神奇3分鐘3球,10人巴薩3:2加冕,姆巴佩難救阿隆索!

話體壇
2026-01-12 05:54:05
爭議!烏克蘭名將0-2不敵薩巴倫卡 拒絕握手:我的國家正承受災(zāi)難

爭議!烏克蘭名將0-2不敵薩巴倫卡 拒絕握手:我的國家正承受災(zāi)難

風(fēng)過鄉(xiāng)
2026-01-11 21:45:41
馬杜羅警衛(wèi)稱美軍突襲時(shí)用神秘武器讓人吐血癱倒,這可能是什么?

馬杜羅警衛(wèi)稱美軍突襲時(shí)用神秘武器讓人吐血癱倒,這可能是什么?

之乎者也小魚兒
2026-01-11 17:23:35
U23亞洲杯一夜亂了:泰國絕平伊拉克起死回生 國足再拿1分就出線

U23亞洲杯一夜亂了:泰國絕平伊拉克起死回生 國足再拿1分就出線

侃球熊弟
2026-01-12 00:05:34
手戴1000多萬名表,坐擁3.6億私人飛機(jī),“滬上皇”秦奮啥來頭?

手戴1000多萬名表,坐擁3.6億私人飛機(jī),“滬上皇”秦奮啥來頭?

小熊侃史
2026-01-12 07:40:07
我連夜啃完馬斯克這173分鐘視頻,很震撼

我連夜啃完馬斯克這173分鐘視頻,很震撼

販財(cái)局
2026-01-11 18:19:53
萬萬沒想到!躲開了王楚欽林詩棟,最后淘汰張本智和的還是中國人

萬萬沒想到!躲開了王楚欽林詩棟,最后淘汰張本智和的還是中國人

十點(diǎn)街球體育
2026-01-12 00:55:03
“死了么”APP創(chuàng)始人:開發(fā)成本1000多元,團(tuán)隊(duì)系三個(gè)95后,計(jì)劃出售10%股份,估值已達(dá)到1000萬元人民幣

“死了么”APP創(chuàng)始人:開發(fā)成本1000多元,團(tuán)隊(duì)系三個(gè)95后,計(jì)劃出售10%股份,估值已達(dá)到1000萬元人民幣

大風(fēng)新聞
2026-01-11 11:03:04
馬斯克拋出2026年九大“瘋狂”預(yù)言:科技狂飆下的未來圖景

馬斯克拋出2026年九大“瘋狂”預(yù)言:科技狂飆下的未來圖景

娛樂督察中
2026-01-11 13:48:02
死傷抗議者過多,伊朗醫(yī)院系統(tǒng)被壓垮!醫(yī)護(hù)連做心肺復(fù)蘇的時(shí)間都沒有

死傷抗議者過多,伊朗醫(yī)院系統(tǒng)被壓垮!醫(yī)護(hù)連做心肺復(fù)蘇的時(shí)間都沒有

互聯(lián)網(wǎng)大觀
2026-01-11 14:31:51
特朗普聽取匯報(bào),威脅最快下周打擊伊朗

特朗普聽取匯報(bào),威脅最快下周打擊伊朗

山河路口
2026-01-11 12:14:33
特朗普:格陵蘭島僅靠狗拉雪橇進(jìn)行防衛(wèi),不管用什么辦法美國都要拿下格陵蘭島

特朗普:格陵蘭島僅靠狗拉雪橇進(jìn)行防衛(wèi),不管用什么辦法美國都要拿下格陵蘭島

環(huán)球網(wǎng)資訊
2026-01-12 08:54:18
斷網(wǎng)、斷電,伊朗180多個(gè)城市發(fā)生激烈沖突

斷網(wǎng)、斷電,伊朗180多個(gè)城市發(fā)生激烈沖突

近距離
2026-01-11 10:59:20
王曼昱輸球原因曝光!郭焱點(diǎn)評(píng)讓人落淚!央視直播多哈冠軍賽決賽

王曼昱輸球原因曝光!郭焱點(diǎn)評(píng)讓人落淚!央視直播多哈冠軍賽決賽

好乒乓
2026-01-11 16:28:04
合川千人殺豬飯后續(xù),一天宰豬五頭,女子漲粉20萬,文旅局忙瘋了

合川千人殺豬飯后續(xù),一天宰豬五頭,女子漲粉20萬,文旅局忙瘋了

天天熱點(diǎn)見聞
2026-01-12 05:51:53
1隊(duì)出線2隊(duì)出局!U23亞洲杯最新晉級(jí)形勢:中國隊(duì)輸泰國=基本淘汰

1隊(duì)出線2隊(duì)出局!U23亞洲杯最新晉級(jí)形勢:中國隊(duì)輸泰國=基本淘汰

侃球熊弟
2026-01-12 00:17:32
鬧大了!金華一工廠老板十多歲兒子對(duì)工人吆五喝六,終于集體走人

鬧大了!金華一工廠老板十多歲兒子對(duì)工人吆五喝六,終于集體走人

火山詩話
2026-01-12 05:54:05
怒了!許利民:球員在擺譜、擺大牌,我們輸?shù)氖潜本┑男蜗蠛妥饑?yán)

怒了!許利民:球員在擺譜、擺大牌,我們輸?shù)氖潜本┑男蜗蠛妥饑?yán)

懂球帝
2026-01-11 22:54:27
閆學(xué)晶發(fā)文道歉,“對(duì)不起,我錯(cuò)了!”網(wǎng)友:波及到兒子,她怕了

閆學(xué)晶發(fā)文道歉,“對(duì)不起,我錯(cuò)了!”網(wǎng)友:波及到兒子,她怕了

娛人細(xì)品
2026-01-12 00:01:19
2場0勝!曝41歲曼聯(lián)救火教練6天便下課,周一官宣新帥:索肖出局

2場0勝!曝41歲曼聯(lián)救火教練6天便下課,周一官宣新帥:索肖出局

我愛英超
2026-01-12 07:14:35
2026-01-12 10:24:49
MediaTea
MediaTea
專業(yè)的數(shù)字媒體、新媒體技術(shù)
1701文章數(shù) 72關(guān)注度
往期回顧 全部

科技要聞

小米二手車價(jià)大跳水:SU7半年跌5萬元

頭條要聞

牛彈琴:新的戰(zhàn)爭一觸即發(fā) 美國和以色列可能弄巧成拙

頭條要聞

牛彈琴:新的戰(zhàn)爭一觸即發(fā) 美國和以色列可能弄巧成拙

體育要聞

U23國足形勢:末輪不負(fù)泰國即確保晉級(jí)

娛樂要聞

留幾手為閆學(xué)晶叫屈?稱網(wǎng)友自卑敏感

財(cái)經(jīng)要聞

揭秘“穩(wěn)賺不賠”的代工項(xiàng)目騙局

汽車要聞

2026款宋Pro DM-i長續(xù)航補(bǔ)貼后9.98萬起

態(tài)度原創(chuàng)

房產(chǎn)
手機(jī)
健康
游戲
親子

房產(chǎn)要聞

66萬方!4755套!三亞巨量房源正瘋狂砸出!

手機(jī)要聞

被砍的小米17 Air手機(jī)工程機(jī)現(xiàn)身

這些新療法,讓化療不再那么痛苦

為什么我還愿意玩穿越火線?畢竟現(xiàn)在CF玩家流失率那么高

親子要聞

小小曾已經(jīng)五個(gè)月了,跟他爸一樣,帥氣可愛!

無障礙瀏覽 進(jìn)入關(guān)懷版