带有 __set__ 但没有 __get__ 的描述符如何工作?
How does a descriptor with __set__ but without __get__ work?
我在某处读到过这样一个事实,即您可以使用带 __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__
被添加到描述符协议中,因此无需在描述符中指定名称。这样,你的描述符就可以这样写:
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()
我在某处读到过这样一个事实,即您可以使用带 __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__
被添加到描述符协议中,因此无需在描述符中指定名称。这样,你的描述符就可以这样写:
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()