子类不能直接访问父类私有字段,因python名称重整使其在内存中变为_parentclass__field;子类中__field被重整为_childclass__field,导致无法访问;私有字段实际已被继承并初始化,可通过vars(实例)查看;正确做法是父类提供@property和@setter封装,子类通过公开属性名操作,避免硬编码重整名。

子类不能直接访问父类的私有字段(以双下划线 __ 开头的字段),这不是权限限制,而是 Python 的名称重整(name mangling)机制在起作用:父类中定义的 self.__field 在内存中实际被存为 self._ParentClass__field。子类里写 self.__field 会被解析成 self._ChildClass__field,和父类的存储名不一致,自然读不到。
私有字段确实被继承了,只是“不可见”
调用 vars(子类实例) 可以看到父类私有字段已存在,例如 {'_Person__name': '张三'}。它被初始化了(通过 super().__init__()),但子类方法中无法用原始名访问。
- 父类
__init__执行时,self.__name在父类作用域内被正确重整为_Person__name - 子类方法中写
self.__name,Python 会在子类作用域重整为_Student__name,查无此键
子类安全使用父类私有字段的正确方式
靠封装,不靠硬编码。父类应提供 @property 和 @setter 接口,子类只操作公开属性名。
- 父类用
@name.getter和@name.setter封装对self.__name的读写 - 子类直接用
self.name = ...或print(self.name),逻辑自动走父类验证 - 若需扩展校验(如学生姓名必须含学号前缀),重写 setter 并调用
super().name.fset(self, value)
绝对要避免的写法
别在子类里手动拼接重整后的名字,比如 self._Person__name。
- 父类名一改,所有硬编码就失效
- 破坏封装,让子类依赖父类实现细节
- 调试时临时用
getattr(obj, '_Person__name', None)可以,但生产代码禁用
不复杂但容易忽略:私有字段不是“丢了”,而是藏起来了;子类不该伸手去拿,而该敲门请父类代劳。











