Python的私有属性和受保护属性

想必学习Python的人都知道在创建类的时候, 可以给类的属性前面加上单下划线或者双下划线, 是为了属性不被访问或者不被篡改

那么单下划线和双下划线有什么区别呢? 为什么加上下划线就能不被访问或者不被篡改呢?

我们通过实例来看看, 我们定义一个Vector向量的类, 向量x和y加上分别加上单下划线

In [1]: class Vector:
   ...:     def __init__(self, x, y):
   ...:         self._x = x
   ...:         self._y = y
   ...:

In [2]: my_vector = Vector(1, 2)

In [3]: my_vector.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-dfb91447d064> in <module>()
----> 1 my_vector.x

AttributeError: 'Vector' object has no attribute 'x'
In [4]: my_vector._x
Out[4]: 1

In [5]: my_vector._y
Out[5]: 2

In [6]: my_vector._y = 3

In [7]: my_vector._y
Out[7]: 3

In [8]: my_vector.__dict__
Out[8]: {'_x': 1, '_y': 3}

我们看到, 加单下划线的属性和普通命名的属性没有什么区别, 都可以重新赋值

单下划线表示的私有属性, 指的是一种代码约定, 而不是真的不能访问, 不能访问指的是按照’道理’上讲, 属性名称应该是x和y, 按照想象中的道理上的x和y去访问时, 会报错说没有此属性. 但是我们还是可以加上单下划线去访问和修改.

我们再看看受保护的双下划线是怎样的:

In [1]: class Vector:
    ...:     def __init__(self, x, y):
    ...:         self.__x = x
    ...:         self.__y = y
    ...:
    ...:

In [2]: my_vector = Vector(1, 2)

In [3]: my_vector.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-dfb91447d064> in <module>()
----> 1 my_vector.x

AttributeError: 'Vector' object has no attribute 'x'

In [4]: my_vector.__x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-15-39767555e3b0> in <module>()
----> 1 my_vector.__x

AttributeError: 'Vector' object has no attribute '__x'

In [5]: my_vector.__dict__
Out[5]: {'_Vector__x': 1, '_Vector__y': 2}

In [6]: my_vector._Vector__x
Out[6]: 1

In [7]: my_vector._Vector__y
Out[7]: 2

In [8]: my_vector._Vector__y = 3

In [9]: my_vector.__dict__
Out[9]: {'_Vector__x': 1, '_Vector__y': 3}

我们可以看到定下双下划属性之后, 访问x和__x属性都报没有此属性的错误, 我们查看类的__dict__属性, 发现属性名被修改了, 加上了单下划线和类名称, 但是我们还是可以修改属性的, 只要我们知道这个特性

所以两者都可以叫’私有属性’, 都受到了不同程度的’保护’, 但都不是真正的保护, 前者是自定义规则, 后者是’官方’规则, 如何使用就看个人了