Python双下划线属性是名称改写而非访问控制,旨在避免子类命名冲突;应优先使用@property和单下划线约定实现可控封装。

Python双下划线私有属性不是真私有,而是名称改写
因为__attr根本就不是访问控制机制,而是名称改写(name mangling)——解释器在类定义阶段自动把self.__attr替换成self._ClassName__attr,仅此而已。它不拦截访问、不抛异常、不加密、不设门禁,只是“悄悄改了个名”。所以你用_ClassName__attr能直接读写,完全合法,Python 甚至不会警告你。
为什么设计成可强行访问?设计目标压根就不是隐藏
双下划线机制的唯一正经用途是:防止子类意外覆盖父类的内部属性。比如父类Base里有__cache,子类Derived也定义了__cache,名称改写后它们分别是_Base__cache和_Derived__cache,互不干扰。这不是为了防用户,是防“自己人手滑”。
直接用_ClassName__attr访问的三大风险
这种写法看似能解决问题,但实际埋雷:
- 类名一改(比如
MyClass→UserModel),所有硬编码的_MyClass__data全崩 - 属性被移到父类或抽象基类后,修饰名变成
_ParentClass__data,调用方毫无感知 - IDE 补全失效、mypy 类型检查跳过、单元测试变成“测实现而非接口”,重构成本翻倍
真正该怎么做:用@property + 普通命名
需要控制读写?别碰双下划线,用@property和@attr.setter:
class Rectangle:
def __init__(self, length):
self._length = length # 单下划线约定,非强制但清晰
self._breadth = 0
<pre class="brush:php;toolbar:false;">@property
def breadth(self):
return self._breadth
@breadth.setter
def breadth(self, value):
if value <= 0:
raise ValueError("Breadth must be positive")
self._breadth = value
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
这样外部用rect.breadth = 5,既自然又可控;调试时rect._breadth也一目了然;改实现不影响接口。
最常被忽略的一点:双下划线不是封装工具,是命名冲突保险丝。把它当“私有”用,等于拿螺丝刀当锤子——能砸,但钉子歪得很快。

















