2016-09-26 52 views
3

我讀了一些關於你可以用__set__而沒有__get__描述符的事實。具有__set__但沒有__get__的描述符如何工作?

它是如何工作的?

它算作數據描述符嗎?它是一個非數據描述符嗎?

這裏是一個代碼示例:

class Desc: 
    def __init__(self, name): 
     self.name = name 
    def __set__(self, inst, value): 
     inst.__dict__[self.name] = value 
     print("set", self.name) 

class Test: 
    attr = Desc("attr") 

>>>myinst = Test() 
>>> myinst.attr = 1234 
set attr 
>>> myinst.attr 
1234 
>>> myinst.attr = 5678 
set attr 
>>> myinst.attr 
5678 

回答

5

您的例子已經給描述符是一個數據描述符。

當設置了屬性,任何其他數據描述符,它是最優先的,被稱爲像這樣:

type(myinst).__dict__["attr"].__set__(myinst, 1234) 

這反過來,根據您的__set__方法添加到attr實例字典。

在屬性訪問,描述符中檢查具有__get__方法,但失敗了,導致的搜索被重定向到該實例的字典,像這樣:

myinst.__dict__["attr"] 

如果不是在實例字典中找到,描述符本身被返回。

此行爲不久記錄在data model像這樣:

如果沒有定義__get__(),然後訪問該屬性將 返回描述對象本身,除非是在 對象的實例字典中的價值。

常見用例包括避免{instance: value}描述符內的字典,並以有效的方式緩存值。


在Python 3.6,__set_name__加入到該描述符協議因此消除了對指定的描述符內的名稱的需要。這樣,您的描述符可以這樣寫:

class Desc: 
    def __set_name__(self, owner, name): 
     self.name = name 
    def __set__(self, inst, value): 
     inst.__dict__[self.name] = value 
     print("set", self.name) 

class Test: 
    attr = Desc() 
+0

關於數據模型中記錄的行爲,Raymond的[如何](https://docs.python.org/2/)中有更詳細的描述howto/descriptor.html)指南。 – wim

+0

@wim其實,起初我提出這個問題的原因是因爲它沒有記錄在那裏。沒有'__get__',沒有數據描述符。花了我一段時間來弄清楚它是如何工作的。我想我會自己將它添加到pydocs中。 – Bharel

相關問題