想必学习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__属性, 发现属性名被修改了, 加上了单下划线和类名称, 但是我们还是可以修改属性的, 只要我们知道这个特性
所以两者都可以叫’私有属性’, 都受到了不同程度的’保护’, 但都不是真正的保护, 前者是自定义规则, 后者是’官方’规则, 如何使用就看个人了