python私有属性通过名称改编(如__attr→_classname__attr)实现“防手误”而非真正访问控制,适用于避免子类命名冲突,但不适用于安全隔离或序列化场景。

Python私有属性不是真的私有,而是靠名称改编
Python没有真正意义上的访问控制,__name 这种双下划线开头的属性不会被直接禁止访问,只是触发了名称改编(name mangling):解释器会自动把它重命名为 _ClassName__name。这本质是“防手误”,不是“防破解”。
常见错误现象:
– 以为 obj.__attr 访问不到就等于安全
– 在子类里用相同名字定义 __attr,结果发现和父类的不是同一个变量
– 用 dir(obj) 查不到 __attr,但能看到改编后的名字
- 名称改编只发生在类定义中、以
__开头且**不以__结尾**的标识符上(比如__init__不会被改) - 改编规则固定:
__attr→_MyClass__attr,哪怕类名动态生成也照常执行 - 如果真想“隐藏”,优先考虑单下划线
_attr+ 文档约定;双下划线只在明确需要避免子类意外覆盖时用
子类继承时双下划线属性不会被覆盖,但容易误判
父类写 __value,子类也写 __value,两者实际是两个独立变量。因为各自被改编为 _Parent__value 和 _Child__value。这不是 bug,是设计使然——它防止了继承链中名字冲突。
使用场景:
– 类内部封装状态,比如缓存、临时标记,不希望子类无意中用同名变量覆盖
– 实现类似 Java 中 private 的语义意图(仅限当前类使用)
- 调试时别只看
__dict__,要搜_ClassName__attr形式的名字 - 子类想“真正覆盖”父类私有逻辑?不行。得用单下划线或改方法名,或者显式调用
super()._Parent__method() - 如果子类需要读取父类改编后的属性,必须用改编名,比如
self._Parent__value—— 但这等于打破封装,慎用
__slots__ 和双下划线私有属性一起用会出问题
__slots__ 限制实例属性列表,但它只检查赋值时的属性名,而名称改编发生在编译期。如果你在 __slots__ 里写了 __x,Python 会尝试把 __x 当作字面名加入 slots,但实际运行中你访问的是改编后的 _Cls__x,导致 AttributeError。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
错误信息示例:AttributeError: 'MyClass' object has no attribute '__x'(尽管你写了 self.__x = 1)
- 正确做法:在
__slots__中写改编后的名字,比如'_MyClass__x',但这样可读性差、易出错 - 更稳妥的做法:私有属性不用
__slots__管,只把公开/半公开字段放进 slots;或者全用单下划线_x配合__slots__ -
__slots__本身不支持动态名称改编,这是语言机制层面的不兼容,不是配置问题
序列化和调试时双下划线属性容易“消失”
pickle、json.dumps 或 IDE 调试器默认只遍历对象的 __dict__,而改编后的名字藏在里面,但名字不像 __x 那样直观。你可能发现 dump 出来的数据没包含预期的“私有字段”,或者断点时变量窗口不显示它。
性能影响很小,但兼容性风险明显:
– dataclasses.asdict() 默认忽略所有双下划线字段
– pydantic 模型默认不导出 __ 开头字段,除非显式用 Field(repr=False) 或配置 model_config = {'include_private': True}
- 如需参与序列化,要么改用单下划线 + 文档说明,要么在序列化逻辑里手动提取
getattr(obj, '_Cls__x', None) - 调试时快速查看所有改编属性:
[k for k in obj.__dict__.keys() if k.startswith('_MyClass__')] - 别指望 IDE 自动补全
__x—— 它补的是字面名,而实际生效的是改编名,补全失败不等于写错了
名称改编是 Python 解释器默默做的字符串操作,它不改变语法结构,也不阻止反射。真正难处理的,是人误以为它提供了访问控制,然后在序列化、继承、调试环节掉进命名错位的坑里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










