定義
通常,一個(gè) descriptor 是具有“綁定行為”的對象屬性。所綁定行為可通過 descriptor 協(xié)議被自定義的 __get__() , __set__() 和 __delete__() 方法重寫。如果一個(gè)對象的上述三個(gè)方法任意一個(gè)被重寫,則就可被稱為 descriptor。
屬性的默認(rèn)操作是從對象字典中獲取、設(shè)置和刪除一個(gè)屬性。例如,a.x 有一個(gè)查找鏈,先 a.__dict__['x'] ,若沒有則 type(a).__dict__['x'] ,若沒有增往上查找父類直到元類。如果查找鏈中,對象被定義了 descriptor 方法,Python 就會覆蓋默認(rèn)行為。
Descriptor 是一個(gè)強(qiáng)大的工具,雖然開發(fā)者不常接觸到它,但它其實(shí)就是類、屬性、函數(shù)、方法、靜態(tà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__() 方法的對象,若只有 __get__() 方法,則為非數(shù)據(jù) descriptor。如果實(shí)例字典中有和數(shù)據(jù) descriptor 同名的入口,則數(shù)據(jù) descriptor 優(yōu)先級更高。相反,非數(shù)據(jù) descriptor 優(yōu)先級低。
讓 __set__() 方法拋出異常,就能創(chuàng)建一個(gè)只讀數(shù)據(jù) descriptor。
調(diào)用 descriptor
descriptor 可以直接通過方法名調(diào)用。例如, d.__get__(obj) 。
而通過訪問對象屬性,自動調(diào)用 descriptor 才是更通用的做法。例如,如果 d 定義了方法 __get__() ,則 obj.d 會調(diào)用 d.__get__(obj) 。
對于對象, b.x 會被轉(zhuǎn)換成 type(b).__dict__['x'].__get__(b, type(b)) 。而對于類(是的,類也可以調(diào)用), B.x 會被轉(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,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
