Python類中的 私有變量和私有方法


默認情況下,Python中的成員函數和成員變量都是公開的(public),在python中沒有類似public,private等關鍵詞來修飾成員函數和成員變量。
在python中定義私有變量只需要在變量名或函數名前加上 ”__“兩個下划線,那么這個函數或變量就是私有的了。
在內部,python使用一種 name mangling 技術,將 __membername替換成 _classname__membername,也就是說,類的內部定義中,
所有以雙下划線開始的名字都被"翻譯"成前面加上單下划線和類名的形式。
例如:為了保證不能在class之外訪問私有變量,Python會在類的內部自動的把我們定義的__spam私有變量的名字替換成為
_classname__spam(注意,classname前面是一個下划線,spam前是兩個下划線),因此,用戶在外部訪問__spam的時候就會
提示找不到相應的變量。   python中的私有變量和私有方法仍然是可以訪問的;訪問方法如下:
私有變量:實例._類名__變量名
私有方法:實例._類名__方法名()

其實,Python並沒有真正的私有化支持,但可用下划線得到偽私有。   盡量避免定義以下划線開頭的變量!
(1)_xxx      "單下划線 " 開始的成員變量叫做保護變量,意思是只有類實例和子類實例能訪問到這些變量,
需通過類提供的接口進行訪問;不能用'from module import *'導入
(2)__xxx    類中的私有變量/方法名 (Python的函數也是對象,所以成員方法稱為成員變量也行得通。),
" 雙下划線 " 開始的是私有成員,意思是只有類對象自己能訪問,連子類對象也不能訪問到這個數據。
(3)__xxx__ 系統定義名字,前后均有一個“雙下划線” 代表python里特殊方法專用的標識,如 __init__()代表類的構造函數。

下面我們看幾個例子:

【1】

 

[python]  view plain  copy
 
  1. class A(object):  
  2.     def __init__(self):  
  3.         self.__data=[]  #翻譯成 self._A__data=[]  
  4.     def add(self,item):  
  5.         self.__data.append(item) #翻譯成 self._A__data.append(item)  
  6.     def printData(self):  
  7.         print self.__data  #翻譯成 self._A__data  
  8.      
  9. a=A()  
  10. a.add('hello')  
  11. a.add('python')  
  12. a.printData()  
  13. #print a.__data  #外界不能訪問私有變量 AttributeError: 'A' object has no attribute '__data'  
  14. print a._A__data #通過這種方式,在外面也能夠訪問“私有”變量;這一點在調試中是比較有用的!  

運行結果是:
['hello', 'python']
['hello', 'python']
【2】
獲取實例的所有屬性        print a.__dict__
獲取實例的所有屬性和方法  print dir(a)

 

 

[python]  view plain  copy
 
  1. class A():  
  2.     def __init__(self):  
  3.         self.__name='python' #私有變量,翻譯成 self._A__name='python'  
  4.     def __say(self): #私有方法,翻譯成 def _A__say(self)  
  5.         print self.__name #翻譯成 self._A__name  
  6.       
  7. a=A()  
  8. #print a.__name #訪問私有屬性,報錯!AttributeError: A instance has no attribute '__name'  
  9. print a.__dict__ #查詢出實例a的屬性的集合  
  10. print a._A__name #這樣,就可以訪問私有變量了  
  11. #a.__say()#調用私有方法,報錯。AttributeError: A instance has no attribute '__say'  
  12. print dir(a)#獲取實例的所有屬性和方法  
  13. a._A__say() #這樣,就可以調用私有方法了  

運行結果:
{'_A__name': 'python'}
python
['_A__name', '_A__say', '__doc__', '__init__', '__module__']
python

從上面看來,python還是非常的靈活,它的oop沒有做到真正的不能訪問,只是一種約定讓大家去遵守,
比如大家都用self來代表類里的當前對象,其實,我們也可以用其它的,只是大家習慣了用self  。

 

【3】小漏洞:派生類和基類取相同的名字就可以使用基類的私有變量

[python]  view plain  copy
 
  1. class A():  
  2.     def __init__(self):  
  3.         self.__name='python' #翻譯成self._A__name='python'  
  4.       
  5. class B(A):  
  6.     def func(self):  
  7.         print self.__name #翻譯成print self._B__name  
  8.   
  9. instance=B()  
  10. #instance.func()#報錯:AttributeError: B instance has no attribute '_B__name'  
  11. print instance.__dict__  
  12. print instance._A__name  

運行結果:
{'_A__name': 'python'}
python

 

[python]  view plain  copy
 
  1. class A():  
  2.     def __init__(self):  
  3.         self.__name='python' #翻譯成self._A__name='python'  
  4.       
  5. class A(A): #派生類和基類取相同的名字就可以使用基類的私有變量。  
  6.     def func(self):  
  7.         print self.__name #翻譯成print self._A__name  
  8.   
  9. instance=A()  
  10. instance.func()  

運行結果:
python

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM