Python 的 __name 并非真正禁止访问,而是通过名称改写(mangling)机制自动重命名为 _ClassName__name;赋值 p.__name = "haha" 实际新增公有属性,并未修改原私有变量 _Person__name,故 get_name() 仍返回旧值。

Python 的 __name 不是真正意义上的“禁止访问”
它只是触发了 name mangling(名称改写)机制,不是加锁或权限拦截。Python 解释器会把 __name 自动重命名为 _ClassName__name,比如 Person.__name 变成 _Person__name。所以你用 p.__name 找不到,但用 p._Person__name 就能读到——这不是漏洞,是设计使然。
__name 被赋值后为什么 get_name() 还返回旧值?
常见错觉:执行 p.__name = "haha" 看似改了私有变量,其实只是给实例动态加了一个**全新的公有属性**,和类里定义的 self.__name 完全无关。原私有变量仍藏在 _Person__name 里,get_name() 返回的仍是它。
-
p.__name = "haha"→ 新增一个叫__name的公有属性 -
p._Person__name→ 才是真正的私有变量存储位置 -
p.get_name()→ 内部读的是self._Person__name,不受上面那行影响
单下划线 _name 和双下划线 __name 的本质区别
_name 是约定,__name 是机制。前者靠开发者自觉不碰;后者靠解释器自动改名防误覆盖——尤其在继承场景中避免子类同名属性冲突。它不为“保密”,而为“隔离”。
-
_name:IDE 可能标灰、linter 会警告,但运行时完全畅通无阻 -
__name:子类定义同名__x不会覆盖父类的__x,因为各自被 mangling 成_Parent__x和_Child__x -
__name__(双下划线开头+结尾):完全不参与 mangling,是特殊方法/属性,如__init__、__doc__
什么时候真需要绕过 __name 直接访问?
几乎不需要。调试时临时查值可以,但写进生产代码等于埋雷:不同 Python 版本可能调整 mangling 规则,且破坏封装契约。真正该做的是检查是否漏写了 get_/set_ 方法,或确认是否误用 _name 就够用。
立即学习“Python免费学习笔记(深入)”;
最常被忽略的一点:name mangling 只作用于**类定义中出现的**双下划线名。如果在方法里动态拼接字符串赋值,比如 setattr(self, "__name", "x"),这个 "__name" 不会被改写——它压根没被解释器扫描到。


















