Python的类中设置私有变量的实质

继上一篇博客Python面向对象

在上一篇博客中提到了Python中定义类的过程中,变量名前面加两个下划线,可以将该属性设置为私有,外部无法直接调用,但是在后面学习的过程中发现这只是一种伪私有,Python中并不能实现真正的私有,将这些在博客中记录一下


首先还是定义一个Student类,并初始化一个stu对象

1
2
3
4
5
6
7
class  Student(object):
def __init__(self, name, score):
super( Student, self).__init__()
self.__name = name # 属性,加两个下划线表示私有,但这只是伪私有
self.__score = score # 属性,加两个下划线表示私有,但这只是伪私有

stu = Student("lisa", 90)

接下来我们输出的stu自带的__dict__属性,这个属性会将stu拥有的各个属性与属性名以字典的形式返回

1
print(stu.__dict__)

可以看到结果

1
{'_Student__name': 'lisa', '_Student__score': 90}

看看我们发现了什么,之前在类中定义的私有属性的名字都发生了改变,于是猜测python的类中将属性设置为私有只是改变下属性名呢,为了证实我们的猜测,再来试一下,这次添加一个age属性,但是不设置为私有,然后将对象实例化后输出__dict__属性

1
2
3
4
5
6
7
8
9
class  Student(object):
def __init__(self, name, score, age):
super( Student, self).__init__()
self.__name = name # 属性,加两个下划线表示私有,但这只是伪私有
self.__score = score # 属性,加两个下划线表示私有,但这只是伪私有
self.age = age

stu = Student("lisa", 90, 12)
print(stu.__dict__)

结果为

1
{'_Student__name': 'lisa', '_Student__score': 90, 'age': 12}

这样我们就更加肯定我们的猜测了,python在类的定义中将属性设置为私有,只是了改变私有属性的名字,是一种伪私有,实际上从外部仍然可以调用,接下来尝试设置和输出私有属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class  Student(object):
def __init__(self, name, score, age):
super( Student, self).__init__()
self.__name = name # 属性,加两个下划线表示私有,但这只是伪私有
self.__score = score # 属性,加两个下划线表示私有,但这只是伪私有
self.age = age

stu = Student("lisa", 90, 12)
print(stu.__dict__)
stu._Student__name = "tom"
stu._Student__score = 100
print(stu._Student__name)
print(stu._Student__score)
print(stu.__dict__)

可以看到结果为

1
2
3
4
{'_Student__name': 'lisa', '_Student__score': 90, 'age': 12}
tom
100
{'_Student__name': 'tom', '_Student__score': 100, 'age': 12}

我们可以在外部通过改变以后的属性名,直接设置或者输出该私有属性,调用形式就是_类名__属性名

我们也可以通过以下形式从外部调用私有属性

1
2
3
4
5
6
7
8
9
class  Student(object):
def __init__(self, name, score):
super( Student, self).__init__()
self.__name = name # 属性,加两个下划线表示私有,但这只是伪私有
self.__score = score # 属性,加两个下划线表示私有,但这只是伪私有

stu = Student("lisa", 90)
print(stu.__dict__.get("_Student__name"))
print(stu.__dict__.get("_Student__score"))

这个实际上就是利用了字典的get()函数