实例属性访问优先级为实例自身>所属类>父类(按MRO顺序)。先查实例__dict__,存在则返回;删除后回退到类查找;方法、property等描述符触发__get__协议;未找到则按MRO向上搜索,否则抛AttributeError。

绑定后的实例属性访问,优先级遵循“实例自身 > 实例所属类 > 父类(含多继承中的MRO顺序)”这一查找链。
实例属性优先于类属性
当通过实例访问一个属性时,Python首先在实例的 __dict__ 中查找。如果存在(比如通过 self.x = 1 或 obj.x = 2 显式设置),直接返回该值,不会继续向上查找类中同名属性。
- 即使类中定义了同名的类变量或方法,只要实例有该属性,就屏蔽类层级的定义
- 删除实例属性(
del obj.attr)后,再次访问会回退到类中查找
方法与描述符影响实际行为
看似是“属性访问”,但若该名称对应的是方法、property、classmethod 或其他描述符,则触发其 __get__ 协议,实际返回值由描述符逻辑决定,而非简单字典查找。
-
@property定义的属性:每次访问都调用其 getter 方法 - 函数在类中定义(未被装饰):访问时返回绑定方法(
obj.method),本质是描述符调用 - 自定义描述符(含
__get__):完全接管访问逻辑,可动态计算、校验或代理
继承链按 MRO 顺序向上查找
若实例和当前类都未定义该属性,Python 沿着 Method Resolution Order(MRO) 列表逐级向上搜索,直到找到第一个匹配项;找不到则抛出 AttributeError。
- MRO 可通过
ClassName.__mro__查看,遵循 C3 线性化算法 - 注意:类属性被覆盖(如子类重定义同名属性)会中断向上查找,不会跨过子类去取父类的旧值
特殊属性和双下划线名称需额外注意
以双下划线开头(如 __x)的名称会触发名称改写(name mangling),实际存储为 _ClassName__x,这会影响查找路径和可见性。
- 改写仅发生在类定义体中,对实例动态赋值的
__x不改写 - 访问
obj.__x通常查不到(除非恰好有该键),应使用改写后的名称或避免双下划线用于普通属性 -
__dict__、__class__等系统属性有固定语义,不参与常规属性查找逻辑

















