Python子类无法访问父类私有变量的直接原因是name mangling:父类中__name被编译为_Animal__name,子类中同名访问被改写为_Cat__name,二者字段名不同;私有变量实际已被继承,可通过vars()验证。

Python子类访问父类私有变量报AttributeError的直接原因
不是“没继承”,而是Python在编译期对双下划线开头的名称做了自动改写(name mangling),导致子类里找不到原名。比如父类中定义了self.__name,实际在实例字典里存的是self._ParentClass__name。子类如果直接写self.__name,会被改写为self._ChildClass__name——和父类的字段名根本不同。
如何验证私有变量是否真的被继承了
用vars()或__dict__查看子类实例的属性,能清楚看到父类私有变量已存在,只是名字变了:
class Animal:
def __init__(self, name):
self.__name = name
<p>class Cat(Animal):
def show(self):
print(vars(self)) # 输出: {'_Animal__name': 'm'}</p><p>cat = Cat('m')
cat.show()
- 父类
__name→ 实际存储为_Animal__name - 子类若定义自己的
__name→ 存为_Cat__name,不冲突也不覆盖 - 这说明:私有变量被继承了,但“不可见”是语法层的屏蔽,不是内存层的缺失
子类中安全访问父类私有变量的两种方式
不推荐硬编码_ParentClass__name这种形式——它破坏封装且易随父类名变更而失效。更合理的方式是:
- 在父类中提供公有方法(如
get_name()、set_name())来代理访问 - 把字段改为单下划线约定(如
self._name),表明“受保护”,子类可按需使用,但不强制禁止 - 极少数调试场景下,可用
getattr(obj, '_Animal__name', None),但仅限临时排查
为什么super().__init__()能初始化私有变量,但子类方法却读不到
因为super().__init__()是在父类作用域内执行的,此时self.__name被正确解析为self._Animal__name;而子类方法中的self.__name是在子类作用域解析的,变成self._Cat__name,自然为空或报错。
立即学习“Python免费学习笔记(深入)”;
这个细节最容易被忽略:**作用域决定名称改写的前缀,而不是“谁定义的”**。所以哪怕你只写一次__name,只要它出现在不同类的方法体里,就会生成不同的真实字段名。


















