5

我在某处读到了这样一个事实,即你可以有一个带有__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
4

1 回答 1

7

您在示例中给出的描述符是数据描述符。

设置属性后,与任何其他数据描述符一样,它具有最高优先级并被调用,如下所示:

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

这反过来又会attr根据您的__set__方法添加到实例字典中。

在属性访问时,检查描述符是否具有该__get__方法但失败,导致搜索被重定向到实例的字典,如下所示:

myinst.__dict__["attr"]

如果在实例字典中找不到,则返回描述符本身。

这种行为很快记录在数据模型中,如下所示:

如果未定义__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()
于 2016-09-26T19:54:31.230 回答