Python中的私有变量和方法是如何实现的?
今儿早上刚进办公室组里小王就问我:“哥,Python里面不是没那种真正的私有变量吗?那到底咋做到‘私有’的?你以前说过__那种写法,是不是就安全了?”我当时还没醒呢,这问题问得我一下精神了。你别说,这玩意其实挺多新手一开始都弄不明白,我刚学Python那会也觉得神奇,明明啥都能访问,凭啥叫私有。
先说个场景,你们肯定遇到过。就是写个类,比如学生Student,咱都想保护一下人家的分数不被乱改,Java/C++那些一套get/set一顿操作,private那是明着写,外面根本拿不到。但Python嘛,你直接self.score=90,你外头Student().score就能直接搞定,对吧。
不过呢,Python其实有个“小心思”。它规定但凡你变量前面带两个下划线,比如__score,你再去外头Student().__score,一下子报错,说啥找不到。你要是新手肯定懵了,咋没了?其实Python底层搞了个名字改写,叫“name mangling”。把你__score变成了_Student__score,你还真不是随便能改到。
给你看个最常见的小例子哈:
classStudent:
def__init__(self, name, score):
self.name = name
self.__score = score
defget_score(self):
return self.__score
def__secret_method(self):
print("偷偷执行了秘密方法")
stu = Student('小明', 88)
print(stu.name) # 这个直接能打印
print(stu.get_score()) # 通过方法能拿到
# print(stu.__score) # 直接这么写,报错
print(stu._Student__score) # 你非要硬搞,其实还是能拿到
是不是挺有意思,Python其实没真正“锁死”,但平时写代码你不会没事去用_类名__变量名吧,大家都默认这是私有的,别动。属于约定俗成,你动了就不讲武德了哈哈。
其实方法也是一样的套路。比如你想藏个方法,不让外部乱调,你写成def __hidden(self):,别人也只能通过_Student__hidden()这种骚操作去动。平时你import别人的包,看到有些方法或变量是两个下划线开头的,基本都别乱碰——除非你就想调皮试试,翻翻源码什么的。
不过还有一种半公开的,就是单下划线开头,比如_foo。这就是明面上的“不要用”,但其实外部还是能访问。你import *的时候,这种单下划线的变量默认不会被带进来,算是半遮半掩,官方文档里写了,是给你个提醒,别乱用。
有同学又问了,那万一我就是想让外部一丁点都动不了,有没有啥招?说实话,Python真没有彻底意义上的私有,毕竟解释型语言,你用反射、名字改写啥的都能拿到。大多数时候还得靠团队自觉、写清楚注释,真的要安全级别高,那得用别的方式,比如只暴露接口,或者用属性的property机制去保护变量读写,逻辑层面拦一拦。
对了,property用法有点意思,比如你想只让别人读不能直接写:
classPerson:
def__init__(self, age):
self.__age = age
@property
defage(self):
return self.__age
@age.setter
defage(self, value):
if value < 0:
raise ValueError("不能是负数")
self.__age = value
p = Person(18)
print(p.age) # 读没问题
p.age = 25# 改也可以,逻辑里判断了
# p.age = -5 # 这会直接抛异常
这种写法挺多项目都在用,尤其是业务里要做数据校验什么的,直接丢到setter里,省事。
哎,扯远了,刚才还说去楼下买个咖啡,结果聊了这么多,下午再忙一波。总之,Python里的私有就是靠下划线魔法+团队约定,你真想耍流氓,永远能绕过去,但正常开发环境,大家都懂这套规则,别去乱动别人的“私房菜”就行了。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领