輕松理解Python 中的 descriptor
定義
通常,一個(gè) descriptor 是具有“綁定行為”的對(duì)象屬性。所綁定行為可通過(guò) descriptor 協(xié)議被自定義的 __get__() , __set__() 和 __delete__() 方法重寫(xiě)。如果一個(gè)對(duì)象的上述三個(gè)方法任意一個(gè)被重寫(xiě),則就可被稱(chēng)為 descriptor。
屬性的默認(rèn)操作是從對(duì)象字典中獲取、設(shè)置和刪除一個(gè)屬性。例如,a.x 有一個(gè)查找鏈,先 a.__dict__['x'] ,若沒(méi)有則 type(a).__dict__['x'] ,若沒(méi)有增往上查找父類(lèi)直到元類(lèi)。如果查找鏈中,對(duì)象被定義了 descriptor 方法,Python 就會(huì)覆蓋默認(rèn)行為。
Descriptor 是一個(gè)強(qiáng)大的工具,雖然開(kāi)發(fā)者不常接觸到它,但它其實(shí)就是類(lèi)、屬性、函數(shù)、方法、靜態(tài)方法、類(lèi)方法以及 super() 背后的運(yùn)行機(jī)制。
Descriptor 協(xié)議
三個(gè)方法原型如下所示:
descr.__get__(self, obj, type=None) --> value descr.__set__(self, obj, value) --> None descr.__delete__(self, obj) --> None
數(shù)據(jù) descriptor 是同時(shí)具有 __get__() 和 __set__() 方法的對(duì)象,若只有 __get__() 方法,則為非數(shù)據(jù) descriptor。如果實(shí)例字典中有和數(shù)據(jù) descriptor 同名的入口,則數(shù)據(jù) descriptor 優(yōu)先級(jí)更高。相反,非數(shù)據(jù) descriptor 優(yōu)先級(jí)低。
讓 __set__() 方法拋出異常,就能創(chuàng)建一個(gè)只讀數(shù)據(jù) descriptor。
調(diào)用 descriptor
descriptor 可以直接通過(guò)方法名調(diào)用。例如, d.__get__(obj) 。
而通過(guò)訪問(wèn)對(duì)象屬性,自動(dòng)調(diào)用 descriptor 才是更通用的做法。例如,如果 d 定義了方法 __get__() ,則 obj.d 會(huì)調(diào)用 d.__get__(obj) 。
對(duì)于對(duì)象, b.x 會(huì)被轉(zhuǎn)換成 type(b).__dict__['x'].__get__(b, type(b)) 。而對(duì)于類(lèi)(是的,類(lèi)也可以調(diào)用), B.x 會(huì)被轉(zhuǎn)換成 B.__dict__['x'].__get__(None, B) 。
Descriptor 例子
class RevealAccess(object): """A data descriptor that sets and returns values normally and prints a message logging their access. """ def __init__(self, initval=None, name='var'): self.val = initval self.name = name def __get__(self, obj, objtype): print('Retrieving', self.name) return self.val def __set__(self, obj, val): print('Updating', self.name) self.val = val >>> class MyClass(object): ... x = RevealAccess(10, 'var "x"') ... y = 5 ... >>> m = MyClass() >>> m.x Retrieving var "x" 10 >>> m.x = 20 Updating var "x" >>> m.x Retrieving var "x" 20 >>> m.y 5
總結(jié)
以上所述是小編給大家介紹的Python 中的 descriptor,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Python使用PyPDF2?Pillow庫(kù)來(lái)將PDF文件轉(zhuǎn)圖片
這篇文章主要為大家介紹了Python使用PyPDF2?Pillow庫(kù)來(lái)將PDF文件轉(zhuǎn)圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Python中新式類(lèi)與經(jīng)典類(lèi)的區(qū)別詳析
這篇文章主要給大家介紹了關(guān)于Python中新式類(lèi)與經(jīng)典類(lèi)的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python實(shí)現(xiàn)外賣(mài)信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)外賣(mài)信息管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01python dict remove數(shù)組刪除(del,pop)
我們?cè)谟脭?shù)組列表做刪除的時(shí)候,可能選擇2個(gè)方法,一個(gè)是del,一個(gè)是pop方法2013-03-03詳解pyppeteer(python版puppeteer)基本使用
這篇文章主要介紹了詳解pyppeteer(python版puppeteer)基本使用 ,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Python實(shí)戰(zhàn)之大魚(yú)吃小魚(yú)游戲的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Python制作一個(gè)經(jīng)典游戲之大魚(yú)吃小魚(yú),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定幫助,需要的可以參考一下2022-04-04OpenCV學(xué)習(xí)之圖像的分割與修復(fù)詳解
圖像分割本質(zhì)就是將前景目標(biāo)從背景中分離出來(lái)。在當(dāng)前的實(shí)際項(xiàng)目中,應(yīng)用傳統(tǒng)分割的并不多,大多是采用深度學(xué)習(xí)的方法以達(dá)到更好的效果。本文將詳細(xì)介紹一下OpenCV中的圖像分割與修復(fù),需要的可以參考一下2022-01-01