双下划线触发名称改写而非访问控制,解释器将__name重命名为_classname__name以避免继承冲突;单下划线_name仅为约定,不改名;魔术方法如__init__不受影响。

双下划线触发的是名称改写,不是访问控制
Python里__name加双下划线,根本目的不是“锁住不让别人读”,而是让解释器自动把它重命名为_ClassName__name。这个过程叫 name mangling(名称改写),只在类定义内部、且标识符以__开头+不以__结尾时生效。
常见错误现象:AttributeError: 'MyClass' object has no attribute '__name'——这不是报“你没权限”,而是报“这名字根本不存在”,因为 Python 已经悄悄把它改掉了。
为什么非得这么干?就为一个场景:继承时避免子类意外覆盖父类的同名属性。
单下划线\_name 和双下划线\_\_name 的实际区别
_name只是约定,IDE可能标灰、from module import *会忽略它,但代码里照样能直接读写,子类也能随便覆写。
__name则不同:
- 子类定义自己的
__name,会变成_ChildClass__name,和父类的_ParentClass__name完全隔离 - 你仍能手动访问
obj._ParentClass__name,但不能用obj.__name -
__init__、__str__这类前后双下划线的魔术方法完全不受影响——它们不参与改写
什么时候该用 __name,什么时候不该用
用__name的唯一强理由:你正在写一个会被继承的基类,且里面有个关键属性,绝对不能被子类同名定义搞崩逻辑。
其他情况,大概率不需要:
- 想提示“别乱用” → 用
_name就够了 - 想防误导入 →
_name在from mod import *时天然被跳过 - 想藏敏感数据(如 token)→ 下划线毫无作用,得靠
property+ 运行时校验 + 文档约束 - 写测试或调试时需要临时读取 → 直接上
obj._ClassName__name,但别提交到生产代码里
容易被忽略的关键细节
名称改写只发生在类体内部;在函数里、模块顶层、或者字符串拼接中写的"__name",都不会被改写。
类名本身如果带下划线(比如My_Class),改写后是_My_Class__name,中间那个下划线保留——这点常被忽略,导致手写访问时出错。
如果你看到别人在子类里反复用self._ParentClass__x去“绕过私有”,说明设计已经偏离初衷:双下划线本意是让父子各管各的,不是用来跨类挖数据的。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











