python数据和非数据描述符
根据, 定义了python数据和非数据描述符,python,descriptor,python-descriptors,Python,Descriptor,Python Descriptors,根据, 定义了\uuuu set\uuuu()和\uuu get\uuuu()的数据描述符始终覆盖实例字典中的重新定义 我理解这句话没有问题,但有人能为我澄清一下为什么会有这样的规定吗?毕竟,如果我想覆盖实例字典中的一个属性,我已经需要明确地这样做(inst.\uu dict\uuu[“attr”]=val),因为一个幼稚的inst.attr=val将调用描述符的\uu set\uu方法,而该方法(通常)不会覆盖实例字典中的属性 编辑:我明白发生了什么,我的问题是为什么要制定这样的规则。覆盖适用
\uuuu set\uuuu()
和\uuu get\uuuu()
的数据描述符始终覆盖实例字典中的重新定义
我理解这句话没有问题,但有人能为我澄清一下为什么会有这样的规定吗?毕竟,如果我想覆盖实例字典中的一个属性,我已经需要明确地这样做(inst.\uu dict\uuu[“attr”]=val
),因为一个幼稚的inst.attr=val
将调用描述符的\uu set\uu
方法,而该方法(通常)不会覆盖实例字典中的属性
编辑:我明白发生了什么,我的问题是为什么要制定这样的规则。覆盖适用于类
\uuuu dict\uuu
中的描述符
Python将始终查找type(instance)。\uuuuu dict\uuuuu[attributename]。\uuuu get\uuuu(instance,type(instance))
,并且不会使用instance.\uuuu dict\uuu
来搜索实例重写
下面是一个使用人工设计的描述符
类和属性(这是一个带有\uuuuu get\uuuuuuu
和\uuuu set\uuuuuuu
的描述符)的示例:
>>> class Descriptor(object):
... def __init__(self, name):
... self.name = name
... def __get__(self, instance, cls):
... print 'Getting %s, with instance %r, class %r' % (self.name, instance, cls)
...
>>> class Foo(object):
... _spam = 'eggs'
... @property
... def spam(self):
... return self._spam
... @spam.setter
... def spam(self, val):
... self._spam = val
...
>>> Foo().spam
'eggs'
>>> foo = Foo()
>>> foo.__dict__['spam'] = Descriptor('Override')
>>> foo.spam
'eggs'
如您所见,即使我在实例\uuuuu dict\uuuu
中添加了spam
条目,它也被完全忽略,并且仍然使用Foo.spam
属性。Python忽略了实例\uuu dict\uuuuu
,因为spam
属性定义了\uu get\uuuu
和\uu集
如果您使用的描述符未定义\uuuuu set\uuuu
,则覆盖会起作用(但它的\uuuu get\uuuu
不会被调用:
>>> class Foo(object):
... desc = Descriptor('Class-stored descriptor')
...
>>> Foo.desc
Getting Class-stored descriptor, with instance None, class <class '__main__.Foo'>
>>> Foo().desc
Getting Class-stored descriptor, with instance <__main__.Foo object at 0x1018df510>, class <class '__main__.Foo'>
>>> foo = Foo()
>>> foo.__dict__['desc'] = Descriptor('Instance-stored descriptor')
>>> foo.desc
<__main__.Descriptor object at 0x1018df1d0>
>>类Foo(对象):
…desc=描述符('类存储描述符')
...
>>>Foo.desc
获取类存储描述符,无实例,类
>>>Foo().desc
获取类存储描述符,带有实例、类
>>>foo=foo()
>>>foo.\uuuuu dict\uuui['desc']=描述符('实例存储描述符')
>>>foo.desc
以下是CPython 2.7.3的实现:和。顺序是数据描述符、实例属性、非数据描述符,最后(仅获取)一个类属性。是的,我已经理解了这一部分。我的问题更多的是关于这一规则的基本原理;也就是说,我永远不会“意外地”在实例中重写类的数据描述符(即,为此,我需要访问dict)那么,如果我真的想这么做,为什么不允许我这么做呢?@antony:这是一个简洁的决定,要获得更详细的解释,请参见;但它的缺点是,您不能覆盖实例\uuuuuuu class\uuuuuuuuuu
中的静态属性,如\uuuuuuuuuuu dict\uuuuuuuu
。仍然不相信(同样,我的观点是Python的方法通常是其中之一)“同意的成年人”和摆弄\uuuu dict\uuuuu
应该会得到你想要的——如果我想在遵守描述符协议的同时动态更新属性,我可以使用setattr
)但我想我不应该在这里讨论语言设计。相反,在我看来,实现的方法效率较低:现在必须检查数据描述符的类型dict,然后检查非描述符属性的实例dict,然后再次检查非数据描述符的类型dict。