私有属性、方法——Python并没有真正的私有化支持,但可用下划线得到伪私有
尽量避免定义以下划线开头的变量
(1)xxx 公有变量
(2)_xxx "单下划线 " 开始的成员变量叫做保护变量,意思是只有类对象(即类实例)和子类对象自己能访问到这些变量,需通过类提供的接口进行访问;不能用'from module import *'导入
(3)__xxx 类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。)," 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。(4)__xxx__ 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__() 代表类的构造函数。
实例解析
(1)公有变量不用多解释,就是可以公共访问的变量
(2)_xxx:前置单下划线的变量
privatization.py
num = 100
_num = 200
__num = 300
class Private(object):
'''私有化'''
def __init__(self):
self.xxx = 'xxx'
self._xxx = '_xxx'
self.__xxx = '__xxx'
def Get__xxx(self):
return self.__xxx
不能用'from module import *'导入
In [1]: from privatization import *
In [2]: num
Out[2]: 100
In [3]: _num
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-a3b2dccd37c6> in <module>()
----> 1 _num
NameError: name '_num' is not defined
In [4]: __num
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-4-560eb7fca2ba> in <module>()
----> 1 __num
NameError: name '__num' is not defined
但是可以通过import module进行访问
In [6]: import privatization as p
In [7]: p.num
Out[7]: 100
In [8]: p._num
Out[8]: 200
In [9]: p.__num
Out[9]: 300
以下是通过'from module import *'导入的类对象访问的,所以可以直接的访问
from privatization import *
In [7]: private = Private()
In [8]: private.xxx
Out[8]: 'xxx'
In [9]: private._xxx
Out[9]: '_xxx'
(3)__xxx:前置双下划线私有变量
if __name__ == '__main__':
private = Private()
print(private.xxx)
print(private._xxx)
# __xxx:双前置下划线的私有属性,无法在外部直接访问(名字重整所以访问不到)
#print(private.__xxx)
# 因为python内部解释器将名字重整,所以报错为:AttributeError: 'Private' object has no attribute '__xxx'
# 所以只要知道重整后的名字就可以直接访问
#print(dir(private)) # 获取对象的所有属性和方法
'''
['_Private__xxx', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_xxx', 'xxx']
'''
# 可以看到python将名字重整为_类名__xxx, 所以可以通过改名字直接访问
print(private._Private__xxx)
# 也可以通过公有方法简介获取
print(private.Get__xxx())
# 如果在类中向__名字赋值,那么会在类中定义的一个与类相同名字的属性
private.__xxx = 'new __xxx'
print(private.__xxx)
总结
- 父类中属性名为
__名字
的,子类不继承,子类不能访问 - 如果在子类中向
__名字
赋值,那么会在子类中定义的一个与父类相同名字的属性 _名
的变量、函数、类在使用from xxx import *
时都不会被导入