【1】默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量。
在python中定义私有变量只需要在变量名或函数名前加上 ”__“两个下划线,那么这个函数或变量就是私有的了。
在内部,python使用一种 name mangling 技术,将 __membername替换成 _classname__membername,也就是说,类的内部定义中,所有以双下划线开始的名字都被"翻译"成前面加上单下划线和类名的形式。
例如:为了保证不能在class之外访问私有变量,Python会在类的内部自动的把我们定义的__spam私有变量的名字替换成为
_classname__spam(注意,classname前面是一个下划线,spam前是两个下划线),因此,用户在外部访问__spam的时候就会
提示找不到相应的变量。 python中的私有变量和私有方法仍然是可以访问的;访问方法如下:
私有变量:实例._类名__变量名
私有方法:实例._类名__方法名()
#coding:utf-8
class A(object):
def __init__(self):
self.__data = [] # 翻译成 self._A__data=[]
def add(self, item):
self.__data.append(item) # 翻译成 self._A__data.append(item)
def printData(self):
print self.__data # 翻译成 self._A__data
a = A()
a.add('hello')
a.add('python')
a.printData()
# print a.__data #外界不能访问私有变量 AttributeError: 'A' object has no attribute '__data'
print a._A__data # 通过这种方式,在外面也能够访问“私有”变量;这一点在调试中是比较有用的!
【2】获取实例的所有属性 print a.__dict__
获取实例的所有属性和方法 print dir(a)
#coding:utf-8
class A():
def __init__(self):
self.__name = 'python' # 私有变量,翻译成 self._A__name='python'
def __say(self): # 私有方法,翻译成 def _A__say(self)
print self.__name # 翻译成 self._A__name
a = A()
# print a.__name #访问私有属性,报错!AttributeError: A instance has no attribute '__name'
print a.__dict__ # 查询出实例a的属性的集合
print a._A__name # 这样,就可以访问私有变量了
# a.__say()#调用私有方法,报错。AttributeError: A instance has no attribute '__say'
print dir(a) # 获取实例的所有属性和方法
a._A__say() # 这样,就可以调用私有方法了
【3】小漏洞:派生类和基类取相同的名字就可以使用基类的私有变量
#coding:utf-8
class A():
def __init__(self):
self.__name = 'python' # 翻译成self._A__name='python'
class B(A):
def func(self):
print self.__name # 翻译成print self._B__name
instance = B()
# instance.func()#报错:AttributeError: B instance has no attribute '_B__name'
print instance.__dict__
print instance._A__name