蟒数据和非数据描述符(python data and non-data descriptors)

2019-07-01 16:39发布

根据Python的文档 ,

与数据描述符__set__()__get__()总是被定义覆盖一个实例字典的重新定义。

我没有问题,理解了这句话,但有人可以澄清我为什么这样的规则是否到位? 毕竟,如果我想在一个实例字典重写的属性,我已经需要做的是明确地inst.__dict__["attr"] = val ),作为一个天真inst.attr = val会打电话描述符的__set__方法,这将(通常)不能取代在实例字典的属性。

编辑:只是要清楚,我明白发生了什么,我的问题是,为什么这样的规则已经到位。

Answer 1:

该覆盖适用于属于的一部分描述__dict__

Python会始终查找type(instance).__dict__[attributename].__get__(instance, type(instance))不会instance.__dict__搜索一个实例覆盖。

下面是一个使用一个人为的一个例子Descriptor的类和属性(其是具有描述符__get____set__

>>> 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'

正如你所看到的,即使我添加spam的实例项__dict__ ,它完全忽略, Foo.spam属性是用来仍。 Python是忽略了实例__dict__ ,因为spam属性定义了__get____set__

如果您使用的是没有定义的描述符__set__倍率有效(但它__get__不叫:

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


文章来源: python data and non-data descriptors