參考鏈接: Python中的私有變量
我們這里就直奔主題,不做基礎鋪墊,默認你有一些Python類的基礎,大家在看這篇博客的時候,如果基礎知識忘了,可以去菜鳥教程?
從一個簡單的類開始?
class A():? ? ? ?#定義一個類 A
? ? a? ? ?= 100? #公有變量
? ? _b? ? = 200? #公有變量
? ? __c? ?= 300? #私有變量
? ? __d__ = 400? #公有變量
a = A()? ? ?#實例化一個對象a,當然可以取另外一個名字b
print(a.a,a._b,a.__c,a.__d__)? ?#打印四個變量的值
?
運行結果: Traceback (most recent call last): File “c:\users\12090\desktop\a.py”, line 7, in? print(a.a,a._b,a.__c,a.d) AttributeError: ‘A’ object has no attribute ‘__c’?
?
??
? ?
??
?
運行結果,提示__c不能訪問,這里的錯誤信息,并沒有指出__c是私有變量,在類外不能訪問 我們程序這樣改動??
通過成員函數間接訪問私有變量?
?
a=A,和a=A()的區別?
我們把第8行改造一下: 去掉括號,就像這樣:??
a = A會成功生成對象a,而且通過對象a可以正確訪問到公有變量a,_b,d。但是在調用函數print_c()的時候,出問題,錯誤提示 TypeError: print_c() missing 1 required positional argument: ‘self’ 提示缺少參數,怎么解決這個問題呢: 顯示傳遞一個類,或者對象進去? 那么a=A,和a=A()有什么區別呢? 區別是: 如果是a=A,則不會調用類中的構造函數; 如果是a=A(),則會調用構造函數;?
A()會調用構造函數?
我們來做一個實驗, python中的構造函數名是系統規定的,init,添加后如下:?
class A():? ? ? ?#定義一個類 A
? ? a? ? ?= 100? #公有變量
? ? _b? ? = 200? #公有變量
? ? __c? ?= 300? #私有變量
? ? __d__ = 400? #公有變量
? ? def __init__(self):? ?#構造函數定義
? ? ? ? print('calling __init__....')
? ? def print_c(self):? #通過成員函數訪問私有變量
? ? ? ? return self.__c
a = A? ? ? ? ? #不會調用構造函數
print(a.a,a._b,a.print_c(a),a.__d__)
b = A()? ? ? ? #會調用構造函數? ?
print(b.a,b._b,b.print_c(),b.__d__)
?
運行結果:? 當我們通過A()這種形式構造對象的時候,會顯示調用構造函數__init__。 當我們通過A這種形式構造對象的時候,不會調用構造函數。?
構造函數,構造了什么?
“構造”這個詞,是一個動詞,就是要造一個東西,那么造什么呢,其實我們上面的例子,可能讓初學者有點不明所以,所以接下來,我們讓構造函數做點有意義的事情,程序如下:?
class A():? ? ? ?#定義一個類 A
? ? a? ? ?= 100? #公有變量
? ? _b? ? = 200? #公有變量
? ? __c? ?= 300? #私有變量
? ? __d__ = 400? #公有變量
? ? def __init__(self,a,b,c,d):? ?#通過構造函數給公有變量或者私有變量重新賦值
? ? ? ? print('構造前:',self.a,self._b,self.__c,self.__d__)
? ? ? ? self.a = a
? ? ? ? self._b = b
? ? ? ? self.__c = c
? ? ? ? self.__d__ = d
? ? ? ? print('構造后:',self.a,self._b,self.__c,self.__d__)
? ? def print_c(self):? #通過成員函數訪問私有變量
? ? ? ? return self.__c
a = A(1000,2000,3000,4000)? ? ? ? ? #通過傳值構造對象
?
運行結果:? 這個例子,就證明了構造函數的作用?
python中 self的作用?
self這個單詞是自己,自我的意思,它代表對象本身,其實你可以換一個單詞也可以,比如you??
照樣可以運行 甚至一個地方用self,一個地方用you也可以??
self的實際意義?
我們一般使用self,python系統也默認是self,但是self的作用遠不止單詞意思這么簡單 比如我們去掉self??
運行起來,好像也沒問題,但是這里的a,_b,__c,d(構造函數里面),并不是公有變量中的a,_b,__c,d。怎么見得呢? 我們把第七行打開? 運行結果出錯: Traceback (most recent call last): File “c:\users\12090\desktop\a.py”, line 13, in? a = A(1000,2000,3000,4000) #調用構造函數 File “c:\users\12090\desktop\a.py”, line 7, in init print(‘構造前:’,a,_b,__c,d) UnboundLocalError: local variable ‘_b’ referenced before assignment?
錯誤原因,是本地變量_b沒有引用,這個local是本地的意思,也就是在構造函數__init__函數作用范圍內。那么第7行的a為什么沒有報錯呢,因為a用的是參數里面的a,并不是公有變量中a。 所以,第12行的打印結果,其實打印的是局部變量,也就是說,在構造函數里面我們定義了一套與公有變量同名的變量,在這種情況下,局部變量優先。 所以,self其實非常有作用,必須通過self來顯示指定公有變量,不然會當作局部變量。 我們還可以進一步說明這個問題?
進一步證明?
?
結論?
Python類中公有變量和私有變量定義一般定義在類名下面,構造函數上面,比如這樣: class A: 公有變量 私有變量 def init(): 。。。 其中私有變量需要有前綴下劃線__ 如果成員函數(包括構造函數),中出現了與公有變量(私有變量)同名的變量,則python系統會屏蔽公有變量和私有變量,把改變量當成局部變量。如果要在成員函數(包括構造函數)使用公有變量和私有變量,必須通過self顯示指定,就像這樣: class A: a = 100 _b = 200 __c = 300 def init(self,a,b,c): self.a = a #使用公有變量a _b = b #屏蔽了公有變量_b,重新定義了一個局部變量_b self.__c =c #使用私有變量__c