python - 带有 __set__ 但没有 __get__ 的描述符如何工作?

标签 python python-descriptors

我在某处读到过这样一个事实,你可以使用 __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

最佳答案

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

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

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

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

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

myinst.__dict__["attr"]

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

此行为很快记录在 data model 中像这样:

If it does not define __get__(), then accessing the attribute will return the descriptor object itself unless there is a value in the object’s instance dictionary.

常见用例包括避免在描述符中使用 {instance: value} 字典,并以高效的方式缓存值。


在 Python 3.6 中,__set_name__ 被添加到描述符协议(protocol)中,因此无需在描述符中指定名称。这样,您的描述符就可以这样写:

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()

关于python - 带有 __set__ 但没有 __get__ 的描述符如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39711281/

相关文章:

python - 组成:为什么 "container instance"改变时 "contained instance"属性没有更新?

python - 在 Python 中使用描述符协议(protocol)时如何获取属性名称?

python -/usr/bin/ld : cannot find -lpython3. 5m

python - 如何在 Django 1.5 中覆盖用户模型的 __unicode__ 方法

python - paInt32、paInt16、paInt24、paFloat32 等之间的区别?

python - 装饰方法时访问绑定(bind)方法或自身

python - 了解 __get__ 和 __set__ 以及 Python 描述符

python - 在 Django webapp 中处理计算密集型任务

python - 如何在Python中关闭绘图窗口后设置绘图标题