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

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

Python:描述符對(duì)象

0
分享至

在 Python 的對(duì)象模型中,描述符對(duì)象(Descriptor Objects)是支撐語言動(dòng)態(tài)特性的核心機(jī)制之一。從最基礎(chǔ)的屬性訪問,到復(fù)雜的元編程框架(如 Django ORM、SQLAlchemy、Pydantic 的字段系統(tǒng)),描述符始終處于幕后,卻決定著屬性系統(tǒng)的最終行為。

如果說 __dict__ 體系提供了屬性數(shù)據(jù)的靜態(tài)存儲(chǔ)結(jié)構(gòu),那么描述符對(duì)象就是介入這一結(jié)構(gòu)之上的動(dòng)態(tài)訪問控制層。

需要強(qiáng)調(diào)的是,描述符不是特殊語法或內(nèi)建魔法,而是完全遵循 Python 對(duì)象模型的普通對(duì)象。

一、描述符對(duì)象的概念

(1)描述符是對(duì)象

在 Python 中,一切皆對(duì)象。描述符也不例外:

? 它是某個(gè)類的實(shí)例

? 擁有自身的類型、屬性與方法

? 可以被賦值、傳遞并存儲(chǔ)于 __dict__ 中

d = Descriptor()

在這一層面上,d 與任何普通對(duì)象并無區(qū)別。

(2)描述符語義的由來

描述符之所以獲得特殊語義,并非源于其“身份”,而在于其實(shí)現(xiàn)了特定的協(xié)議方法,并且位于類屬性位置。

當(dāng)一個(gè)對(duì)象同時(shí)滿足以下條件時(shí),在屬性訪問過程中,就會(huì)被解釋器識(shí)別為描述符對(duì)象:

? 實(shí)現(xiàn) __get__()、__set__()、__delete__() 中至少一個(gè)

? 作為類屬性存在于另一個(gè)類的 __dict__ 中

二、描述符的存儲(chǔ)位置與作用范圍

(1)描述符的存儲(chǔ)位置

描述符對(duì)象在參與屬性訪問控制時(shí),必須作為類屬性存在于另一個(gè)類對(duì)象的 __dict__ 中。

    x = D()   # 描述符對(duì)象存放在 A.__dict__ 中

此處的 D() 是一個(gè)普通對(duì)象,但由于它位于 A.__dict__ 中,因此進(jìn)入屬性查找鏈。

(2)描述符的作用對(duì)象

盡管描述符存在于類級(jí)別,但其控制的卻是:

? 實(shí)例屬性的訪問

? 類屬性的訪問行為(當(dāng) instance is None)

比如:

print(a.x)    # 輸出:descriptor

因?yàn)樵撛L問會(huì)被解釋為:

A.__dict__['x'].__get__(a, A)

從語言規(guī)范角度看,描述符對(duì)象本質(zhì)上是對(duì)的實(shí)現(xiàn)。這些協(xié)議方法不是“魔法”,而是 Python 在屬性查找過程中主動(dòng)調(diào)用的標(biāo)準(zhǔn)接口。

三、描述符對(duì)象的分類

根據(jù)是否攔截屬性寫入或刪除操作,描述符可分為兩類:數(shù)據(jù)描述符(Data Descriptor)和非數(shù)據(jù)描述符(Non-data Descriptor)。

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

定義:實(shí)現(xiàn)了 __set__() 和 / 或 __delete__(),通常同時(shí)實(shí)現(xiàn)了 __get__() 方法。

行為特征:在屬性查找順序中優(yōu)先級(jí)高于實(shí)例 __dict__,因此實(shí)例無法通過同名屬性繞過其控制。

示例:

        obj.__dict__[self.storage_name] = value

作為類屬性使用:

    balance = Positive()

訪問行為驗(yàn)證:

print(a.__dict__) # 輸出 {'_balance': 100, 'balance': -999}

在 Python 的世界里,沒有什么能完全阻止一個(gè)想要直接操作 __dict__ 的開發(fā)者,但描述符能確保通過“正規(guī)途徑”(即 a.balance = val)進(jìn)入的數(shù)據(jù)一定是合法的。真正的保護(hù)應(yīng)將存儲(chǔ)名(如 _balance)與屬性名(balance)分離。

(2)非數(shù)據(jù)描述符

定義:僅實(shí)現(xiàn) __get__() 方法。

行為特征:優(yōu)先級(jí)低于實(shí)例 __dict__,因此可被實(shí)例屬性遮蔽。

示例:

        return value

作為類屬性使用:

        return 42

訪問行為驗(yàn)證:

print(d.value)   # 第二次:直接從 d.__dict__ 取值,42,不再觸發(fā)描述符

以上示例利用非數(shù)據(jù)描述符優(yōu)先級(jí)低于實(shí)例 __dict__ 的特性實(shí)現(xiàn)“惰性求值”:首次訪問時(shí)觸發(fā)計(jì)算并將結(jié)果緩存至實(shí)例 __dict__ ;后續(xù)訪問則因?qū)嵗龑傩浴罢诒巍绷嗣枋龇苯幼x取緩存,從而有效避免重復(fù)計(jì)算,優(yōu)化運(yùn)行性能。

四、Python 內(nèi)置的描述符對(duì)象

Python 中的大量核心對(duì)象,本身就是描述符對(duì)象。

(1)函數(shù)對(duì)象:非數(shù)據(jù)描述符

類中定義的函數(shù)對(duì)象本身是非數(shù)據(jù)描述符。通過其 __get__() 方法,Python 實(shí)現(xiàn)了實(shí)例方法的自動(dòng)綁定。

a = A()

當(dāng)訪問方法 foo:

a.foo

本質(zhì)是:

A.__dict__['foo'].__get__(a, A)

從而生成綁定方法(Bound Method)。

(2)@property:標(biāo)準(zhǔn)數(shù)據(jù)描述符

@property 返回的是標(biāo)準(zhǔn)的數(shù)據(jù)描述符對(duì)象(實(shí)現(xiàn)了 __get__()、__set__() 和 __delete__()),用于將屬性訪問映射為函數(shù)調(diào)用。

示例:

        self._age = value

訪問行為:

p.age = 30       # 調(diào)用 property.__set__

可以這樣說,@property 是描述符機(jī)制的官方封裝版本。

(3)@classmethod 與 @staticmethod

這兩個(gè)裝飾器均返回描述符對(duì)象,分別實(shí)現(xiàn)對(duì)類對(duì)象或函數(shù)本身的不同綁定策略。

示例:

        return "no binding"

訪問驗(yàn)證:

print(Demo().static_method()) # 仍不綁定

classmethod 的描述符在 __get__() 中綁定 owner。staticmethod 的描述符在 __get__() 中直接返回函數(shù)。二者都是描述符對(duì)象,只是綁定策略不同。

五、描述符對(duì)象在屬性查找鏈中的位置

當(dāng)執(zhí)行 obj.attr 時(shí),Python 的查找順序?yàn)椋?/p>

1、類 __dict__ 中的數(shù)據(jù)描述符

2、實(shí)例 obj.__dict__

3、類 __dict__ 中的非數(shù)據(jù)描述符

4、類 __dict__ 中的普通屬性

5、__getattr__() 方法

描述符的“權(quán)力”并非絕對(duì),而是由協(xié)議與順序共同決定的。

六、描述符的現(xiàn)代最佳實(shí)踐:__set_name__

Python 3.6 之后,引入了:

__set_name__(self, owner, name)

__set_name__() 方法在類創(chuàng)建階段被自動(dòng)調(diào)用,使描述符對(duì)象能夠獲知自身的屬性名與所屬類。這是當(dāng)前描述符實(shí)現(xiàn)的標(biāo)準(zhǔn)范式。

示例:

        setattr(obj, self.storage_name, value)

描述符作為類屬性使用:

    salary = Typed()

此時(shí)在類創(chuàng)建過程中,解釋器會(huì)隱式執(zhí)行:

Typed.__set_name__(Employee, "salary")

實(shí)際訪問行為如下:

print(e.salary)   # 輸出:8000

底層狀態(tài):

e.__dict__ == {"_age": 30, "_salary": 8000}

實(shí)際數(shù)據(jù)存儲(chǔ)在實(shí)例的 __dict__ 中,而訪問路徑始終經(jīng)過類 __dict__ 中的描述符對(duì)象。

上例說明:

? Typed() 本身是一個(gè)普通對(duì)象。

? 它存在于 Employee.__dict__。

? 通過 __set_name__ 獲得屬性名。

? 通過 __get__ / __set__ 管理實(shí)例數(shù)據(jù)。

? 實(shí)例并不直接暴露真實(shí)存儲(chǔ)字段。

這一結(jié)構(gòu)正是現(xiàn)代描述符實(shí)現(xiàn)的標(biāo)準(zhǔn)范式,也是 ORM、字段系統(tǒng)、類型系統(tǒng)中最常見的設(shè)計(jì)基礎(chǔ)。


小結(jié)

描述符對(duì)象是 Python 屬性系統(tǒng)中的關(guān)鍵組成部分。它們以普通對(duì)象的形式存在于類 __dict__ 中,通過實(shí)現(xiàn)特定協(xié)議方法參與屬性查找過程,從而實(shí)現(xiàn)對(duì)屬性訪問行為的精細(xì)控制。理解描述符,有助于全面把握 Python 對(duì)象模型與屬性機(jī)制的設(shè)計(jì)思想。


點(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)推薦
廣東108-78遼籃!球員評(píng)分:3人滿分,3人良好,1人不合格

廣東108-78遼籃!球員評(píng)分:3人滿分,3人良好,1人不合格

多特體育說
2026-01-11 21:39:19
蔬菜市場遇冷,這3種菜便宜卻沒人買,攤販:現(xiàn)在老百姓太精明了

蔬菜市場遇冷,這3種菜便宜卻沒人買,攤販:現(xiàn)在老百姓太精明了

三農(nóng)雷哥
2026-01-11 17:28:07
萬萬沒想到!李晨會(huì)因?yàn)槔先宋兜巧蠠崴眩杏X他這輩子很難結(jié)婚了

萬萬沒想到!李晨會(huì)因?yàn)槔先宋兜巧蠠崴眩杏X他這輩子很難結(jié)婚了

樂悠悠娛樂
2025-12-02 11:01:18
打平就出線!U23國足成亞洲杯大黑馬:賽后澳大利亞球員低下頭顱

打平就出線!U23國足成亞洲杯大黑馬:賽后澳大利亞球員低下頭顱

足球大腕
2026-01-11 22:02:43
羽壇名將李宗偉:36歲患癌喉嚨全爛,花近1000萬續(xù)命,現(xiàn)狀如何?

羽壇名將李宗偉:36歲患癌喉嚨全爛,花近1000萬續(xù)命,現(xiàn)狀如何?

豐譚筆錄
2026-01-07 10:59:38
遼寧78-108廣東1喜3憂!小將罕見暴走,姜宇星仍崩,2將難打強(qiáng)隊(duì)

遼寧78-108廣東1喜3憂!小將罕見暴走,姜宇星仍崩,2將難打強(qiáng)隊(duì)

籃球資訊達(dá)人
2026-01-11 22:32:21
2026年春節(jié),要暖到離譜?大年初一撞上七九,老輩人:60年頭回見

2026年春節(jié),要暖到離譜?大年初一撞上七九,老輩人:60年頭回見

叮當(dāng)當(dāng)科技
2026-01-07 13:58:49
愛奇藝、騰訊、優(yōu)酷三大平臺(tái)“王炸劇”紛紛登場,誰能登頂劇王?

愛奇藝、騰訊、優(yōu)酷三大平臺(tái)“王炸劇”紛紛登場,誰能登頂劇王?

鄉(xiāng)野小珥
2026-01-12 05:57:22
乒球世界排名更新:朱雨玲第5獲28萬,陳幸同重返第3

乒球世界排名更新:朱雨玲第5獲28萬,陳幸同重返第3

民哥臺(tái)球解說
2026-01-12 05:20:12
氧氣要火了?科學(xué)家發(fā)現(xiàn)寶藏:吸100%純氧3個(gè)月,生理倒拔20歲

氧氣要火了?科學(xué)家發(fā)現(xiàn)寶藏:吸100%純氧3個(gè)月,生理倒拔20歲

科學(xué)認(rèn)識(shí)論
2026-01-11 17:13:05
開國大將次子羅宇,89年攜香港女星叛逃出國,晚年在美國黯然離世

開國大將次子羅宇,89年攜香港女星叛逃出國,晚年在美國黯然離世

搜史君
2025-12-31 13:00:10
形勢突變!別了,北約!美國這次玩真的!

形勢突變!別了,北約!美國這次玩真的!

李榮茂
2026-01-12 07:03:16
哈梅內(nèi)伊開始大范圍斷網(wǎng),革命衛(wèi)隊(duì)將與中俄軍演,伊朗進(jìn)入關(guān)鍵期

哈梅內(nèi)伊開始大范圍斷網(wǎng),革命衛(wèi)隊(duì)將與中俄軍演,伊朗進(jìn)入關(guān)鍵期

溫讀史
2026-01-10 07:33:53
拉菲尼亞雙響鎖定勝局,巴薩3-2皇馬衛(wèi)冕西超杯

拉菲尼亞雙響鎖定勝局,巴薩3-2皇馬衛(wèi)冕西超杯

浮萍足球
2026-01-12 07:24:06
廣西又有2名干部向紀(jì)委投案自首!

廣西又有2名干部向紀(jì)委投案自首!

嶺南美玉
2026-01-12 00:08:15
我只認(rèn)出了萬梓良 ,你們呢 ?

我只認(rèn)出了萬梓良 ,你們呢 ?

小椰的奶奶
2026-01-12 01:45:27
為保護(hù)馬杜羅夫妻戰(zhàn)死的古巴桑切斯上校,被曝光家人都住在美國!

為保護(hù)馬杜羅夫妻戰(zhàn)死的古巴桑切斯上校,被曝光家人都住在美國!

阿龍聊軍事
2026-01-09 20:20:47
伊朗政府宣布全國哀悼三天

伊朗政府宣布全國哀悼三天

界面新聞
2026-01-12 07:03:21
沒想到竟然這么多工作需要保密的!網(wǎng)友:不讓看非看被一槍斃了

沒想到竟然這么多工作需要保密的!網(wǎng)友:不讓看非看被一槍斃了

另子維愛讀史
2025-12-08 20:58:22
汪小菲為什么發(fā)瘋,發(fā)瘋背后是流量斷崖式的下跌

汪小菲為什么發(fā)瘋,發(fā)瘋背后是流量斷崖式的下跌

調(diào)侃國際觀點(diǎn)
2026-01-11 18:41:24
2026-01-12 08:04:49
MediaTea
MediaTea
專業(yè)的數(shù)字媒體、新媒體技術(shù)
1701文章數(shù) 72關(guān)注度
往期回顧 全部

科技要聞

“我們與美國的差距也許還在拉大”

頭條要聞

李獻(xiàn)林學(xué)習(xí)教育期間違規(guī)吃喝:5人喝4瓶酒 1人酒后死亡

頭條要聞

李獻(xiàn)林學(xué)習(xí)教育期間違規(guī)吃喝:5人喝4瓶酒 1人酒后死亡

體育要聞

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

娛樂要聞

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

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

外賣平臺(tái)"燒錢搶存量市場"迎來終局?

汽車要聞

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

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

親子
藝術(shù)
本地
手機(jī)
公開課

親子要聞

最近的孩子怎么都長得這么著急?你不說,誰知道他還是個(gè)寶寶?

藝術(shù)要聞

10位著名畫家的女性人物繪畫,張張經(jīng)典!

本地新聞

云游內(nèi)蒙|“包”你再來?一座在硬核里釀出詩意的城

手機(jī)要聞

真我 Neo8 參數(shù)曝光,驍龍 8 Gen5 、8000mAh電池

公開課

李玫瑾:為什么性格比能力更重要?

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