3.2.6 实例属性的查找顺序
我们知道类的属性都会存储在__dict__
字典中,即使没有显式的给属性赋值,但只要字典里面有这个字段,也是可以读取到的:
但我们在特性工厂和属性描述符的实现中,都是直接把属性的值存储在 __dict__
中,而且键就是属性名。之前我们还介绍过,特性的工作原理是没有直接访问实例的属性,而是读取了 property
的实例。那直接把值存在 __dict__
中,会不会导致特性失效,直接访问到原始内容呢?从之前的实践结果来看,答案是否定的,要解释这个问题,我们需要搞明白访问实例属性的查找顺序。
假设有这么一段代码:
再对上一节中的属性描述符做一个简单的分类:
覆盖型描述符:定义了
__set__
方法的描述符非覆盖型描述符:没有定义
__set__
方法的描述符
在执行 o.attr
时,查找顺序如下:
如果
attr
出现在cls
或父类的__dict__
中,且attr
是覆盖型描述符,那么调用__get__
方法。否则,如果
attr
出现在o
的__dict__
中,返回o.__dict__[attr]
否则,如果
attr
出现在cls
或父类的__dict__
中,如果attr
是非覆盖型描述符,那么调用__get__
方法。否则,如果没有非覆盖型描述符,直接返回
cls.__dict__[attr]
否则,如果
cls
实现了__getattr__
方法,调用这个方法抛出
AttributeError
所以,在访问类的属性时,覆盖型描述符的优先级是高于直接存储在 __dict__
中的值的。
Last updated