成员变量隐藏是同名字段在子类中定义后遮蔽父类同名字段的访问路径,而非覆盖或删除;Python通过属性查找机制实现“就近匹配”,父类字段仍存在但不可直接访问。

继承中成员变量的隐藏,不是“覆盖”也不是“删除”,而是同名字段在子类中定义后,会遮蔽父类中同名字段的直接访问路径。这种现象在 Python 中由属性查找机制决定,关键在于理解“名字在哪里被找到”,而不是“谁替换了谁”。
子类定义同名变量会屏蔽父类字段
当子类在 __init__ 或其他方法中给 self.xxx 赋值,且父类也有 self.xxx 时,子类实例访问 .xxx 得到的是子类赋的值,父类那个字段依然存在,但不再通过默认路径可及:
- 父类 A 中有 self.role = "staff"
- 子类 B 中有 self.role = "manager"
- B() 实例调用 .role → 返回 "manager",不是 "staff"
- 父类字段并未消失,只是被“就近”查找到的子类字段掩盖了
想保留并显式使用父类字段,需手动引用
如果子类既要定义自己的 role,又需要读写父类原始的 role,不能依赖同名访问,而应:
- 改用不同名称(推荐):如父类用 self._base_role,子类用 self._current_role
- 或在子类中显式保存父类值:self._parent_role = super().__getattribute__('role')(不常用)
- 更稳妥的做法是:父类提供受保护的 getter 方法,如 get_base_role(),子类调用它获取原始值
双下划线私有字段不会被真正“隐藏”而是被重整
若父类定义 self.__secret,子类即使定义同名 self.__secret,两者也互不影响:
- 父类中它变成 _A__secret
- 子类中它变成 _B__secret
- 二者内存独立,不存在遮蔽关系;子类访问 self.__secret 永远只能看到自己的重整名
- 所以这不是“隐藏”,而是“隔离”——Python 用名称重整避免意外覆盖,不是访问控制
避免意外隐藏的实用建议
日常开发中减少歧义最有效的方式是:
- 公有字段用清晰、语义明确的名字,避免父子类随意重用同一名称
- 内部使用的字段统一加单下划线前缀(如 _config),并靠文档和约定约束使用范围
- 需要封装的数据,优先用 @property + 私有后备字段(如 __value),对外暴露可控接口
- 调试时可通过 vars(instance) 查看实际存储的所有字段,确认哪些被子类新定义覆盖










