我一直在阅读描述符指南,对这句话感到困惑:
如果一个实例的字典中有与数据描述符同名的条目,则数据描述符优先。
字典如何包含两个具有相同名称的项(普通条目和数据描述符)?或者说,作为描述符的属性是否没有存储在 __dict__
中?
我一直在阅读描述符指南,对这句话感到困惑:
如果一个实例的字典中有与数据描述符同名的条目,则数据描述符优先。
字典如何包含两个具有相同名称的项(普通条目和数据描述符)?或者说,作为描述符的属性是否没有存储在 __dict__
中?
instance.__dict__
)。这些是两个单独的字典,因此这里没有冲突。foo
的实例bar
,Python还会按以下顺序查看它的类(type(bar)
,下面命名为C
):C.foo
。如果它是一个数据描述符,则查找将在此结束。返回C.foo.__get__(bar, C)
。否则,Python将保存此结果以进行步骤3的查找(没有再次查找的意义)。
2. 如果C.foo
不存在或是一个常规属性,则Python会查找bar.__dict__['foo']
。如果存在,则返回它。请注意,如果C.foo
是数据描述符,则永远不会到达此部分!
3. 如果bar.__dict__['foo']
不存在,但C.foo
存在,则使用C.foo
。如果C.foo
是一个(非数据)描述符,则返回C.foo.__get__(bar, C)
。C.foo
实际上是C.__dict__['foo']
,但出于简单起见,我忽略了在类上的描述符访问。)__set__
方法),另一个则不是。>>> class DataDesc(object):
... def __get__(self, inst, type_):
... print('Accessed the data descriptor')
... return 'datadesc value'
... def __set__(self, inst, value):
... pass # just here to make this a data descriptor
...
>>> class OtherDesc(object):
... def __get__(self, inst, type_):
... print('Accessed the other, non-data descriptor')
... return 'otherdesc value'
...
>>> class C(object):
... def __init__(self):
... # set two instance attributes, direct access to not
... # trigger descriptors
... self.__dict__.update({
... 'datadesc': 'instance value for datadesc',
... 'otherdesc': 'instance value for otherdesc',
... })
... datadesc = DataDesc()
... otherdesc = OtherDesc()
...
>>> bar = C()
>>> bar.otherdesc # non-data descriptor, the instance wins
'instance value for otherdesc'
>>> bar.datadesc # data descriptor, the descriptor wins
Accessed the data descriptor
'datadesc value'
class X:
@property
def x(self):
return 2
x1 = X()
x1.__dict__['x'] = 1
print(x1.x)
del inst.foo
有时会到达实例,有时会到达数据描述符。对于设置,当您执行inst.foo ='value'
时,如果已经存在实例属性,是否应该有所影响?谁负责处理设置?通过始终使数据描述符负责,您可以清晰、一致地解决所有这些问题。 - Martijn Pieters__class__
属性永远不应该在实例上设置,因为这样你就无法找到相应的类了,所以在类上,__class__
是一个数据描述符。 - Martijn Pieters