一个下划线表示"别动",两个下划线表示"真别动"!Python属性访问控制,看懂这篇就够了
本文内容整理自道满PythonAI《访问限制》教程
写代码最怕啥?写完一个类,结果外部代码随手把你的核心数据改成了稀奇古怪的值,整个逻辑崩得莫名其妙!
给了学生对象一个分数属性,结果外面直接赋值 -10 分、200 分,数据校验全成摆设。程序是能跑,但数据早就乱套了,这就是封装没做到位!
Python的访问控制全靠"君子协议"------这门语言的设计哲学是"我们都是成年人",它相信程序员会自觉遵守约定。它有套独特的命名规则,更像是一种代码界的"社交礼仪",做到了极致的平衡:该遵守的规矩一条不少,但关键时刻绝不拦着你自己担责。
一、底层原理:为什么Python的设计这么"另类"?
在学习规则之前,得先明白Python为什么这么设计。
面向对象三大特性(封装、继承、多态)里,封装是基础。它的核心不是把属性完全藏起来,而是:把数据和操作数据的方法绑定在一个类里;对外隐藏内部实现细节;只暴露受控制的访问入口。
Python不像Java有强制的private关键字。Python解释器本身不会强制拦截任何访问------这门语言的哲学是"我们都是成年人",相信程序员会自觉遵守约定,不需要语言来强制管束。
Python的访问控制本质就是一种"君子协定":Python告诉你这里有堵墙(单下划线"请勿打扰"),但你非要撞上去,它也不会拦着,只是后果自负。
二、三种访问级别:一个下划线到两个下划线的权限阶梯
教程把Python的访问控制分成了三个级别:
1. 公共成员Public------没什么不能看的
所有属性和方法默认都是公共的,类内部、外部、子类都能随便用。比如定义个学生类,里面的name属性,外部想读就读,想写就写,没有任何限制。
这就是Python的默认行为------简单粗暴,但有时也过于"开放"。
2. 受保护成员Protected------请勿打扰的提示
以单个下划线_开头的成员,属于"受保护"级别。这只是一种命名约定,表示"内部使用,外部别碰"。
但Python不会真的阻止你访问它------只是如果团队里其他人看到你这么做,会觉得你不太专业。
核心思想是:"Python解释器不强制执行,仅仅是作为对程序员的提示",全靠自觉遵守。
3. 私有成员Private------上了个假锁
以双下划线__开头且不以双下划线结尾的成员,Python解释器会做一个叫"名称修饰"的操作------把它偷偷重命名为_类名__属性名的格式,表面上看外部直接访问会报错。
但这就安全了吗?并没有。如果知道这个改名规则,还是能强行访问:s._Student__name 照样能拿到数据。
所以Python的"私有"不是真正的私有------它更像是给属性贴了个"别碰我"的标签,碰了也能强拆,只是作者觉得拆了后果自负。
三、假锁变真门:受控访问的正确姿势
单纯用双下划线只能防君子不防小人,真正的封装需要配合访问器------在getter里控制读取权限,在setter里做参数验证、类型检查、权限校验等。
1. 传统写法:显式getter/setter
熟悉Java/C++的开发者会习惯这种方式:把属性设为私有,再写get_name()和set_score()方法。
在setter里加上0-100的校验和类型检查,非法数据根本进不来。
但这种方式在Python里显得有些啰嗦------每次访问属性都要写成obj.get_score(),不够优雅。
2. Pythonic写法:@property装饰器(强烈推荐)
Python最优雅的做法是结合双下划线私有属性和@property装饰器,把方法伪装成属性来调用。
用@property装饰getter方法,外部就能像访问普通属性一样用obj.score取值。用@score.setter装饰setter方法,外部像属性赋值一样用obj.score = 85触发里面的校验逻辑。
这样写的好处是:属性访问语法清爽(不用写一堆get和set),同时setter里该做的校验一个不少------兼容了安全性和优雅性,是纯正的"Pythonic"风格。
💡 "靠自觉遵守单下划线约定管控内部接口,用双下划线和
@property守护核心数据的合法性,该松的地方松,该紧的地方紧------分寸感要拿捏到位"。
四、正确理解:封装不止是"隐藏"
很多初学者以为封装就是把属性藏起来不让外面访问。其实不是,封装的核心不是"锁死",而是"受控"。封装的精髓在于:把实现细节隐藏起来,但对外提供清晰、安全、可控的接口。
就像开车,你不需要懂发动机原理,只要会用方向盘和刹车就行。合理封装就是给你方向盘和刹车,而不是把你焊死在驾驶座上不让你碰车。
最后总结
Python的访问控制更像是"君子协议",总结起来就几条:
- 单下划线
_:内部使用的提示,团队协作的潜规则,外部尽量别碰,但Python不拦着。 - 双下划线
__:名称修饰,防子类意外覆盖,外部强行访问也能绕过去。 @property:最Pythonic的封装方式,写出兼具安全性和优雅性的代码。- "我们都是成年人":Python的设计哲学是相信程序员,强制限制不如明确约定。
真正牛的封装不是把属性锁死谁也不让碰,而是设计好该暴露则暴露、该保护则保护的接口。让调用者用得舒服,数据又不能乱来!
评论区聊聊:你第一次知道双下划线还能"绕过去"的时候,是什么心情?
💡 Python 学习不走弯路!
体系化实战路线:基础语法 · 异步Web开发 · 数据采集 · 计算机视觉 · NLP · 大模型RAG实战 ------ 全在「道满PythonAI」!