2017-10-20 149 views
3

我想了解類繼承如何在Python 3中工作,特別是私人領域如何與本地和繼承方法進行交互。這裏有一些例子來說明這個問題。Python3:類繼承和私有字段

首先,如果在超類的變量var是公共的,然後在子類中的任何方法也可以改變它:

class Superclass: 
    var = 1 
    def getVar(self): 
     print(self.var) 

class Subclass(Superclass): 
    def __init__(self): 
     self.var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 123 

同樣是不正確的,如果在超類中的變量__var是私人,任何繼承的方法將忽略由子類進行修改:

class Superclass: 
    __var = 1 
    def getVar(self): 
     print(self.__var) 

class Subclass(Superclass): 
    def __init__(self): 
     self.__var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 1! 

子類中的本地方法可以修改它:

class Superclass: 
    __var = 1 

class Subclass(Superclass): 
    def __init__(self): 
     self.__var = 123 
    def getVar(self): 
     print(self.__var) 

my_object = Subclass() 
my_object.getVar() # outputs 123 

但爲了使用繼承的方法改變了其價值,我必須在子類中使用self._Superclass__var代替self.__var

class Superclass: 
    __var = 1 
    def getVar(self): 
     print(self.__var) 

class Subclass(Superclass): 
    def __init__(self): 
     self._Superclass__var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 123 

爲什麼會出現這種情況?是否私有字段不被子類繼承,因此Subclass中的變量self.__var不指向與Superclass中的變量self.__var相同的值?

+6

Python中沒有專用字段。如果用'__'前綴屬性名稱,則會調用名稱修改,其中自動插入「擁有」類的名稱,以防止在子類中衝突屬性名稱。它並不妨礙你訪問它,它只是要求你包含擁有類的名字。請參閱https://docs.python.org/3/tutorial/classes.html#private-variables – kindall

+4

Python中有*沒有專用字段*。這是你根本的誤解。您正在使用雙下劃線名稱mangling,它可以防止繼承類中的名稱衝突,而不是阻止訪問。另外,我希望你意識到你正在定義*類級變量*,相當於其他語言中的「靜態變量」,而不是實例變量。 –

+1

我認爲值得加上這個澄清作爲一個答案,因爲這是一個很好的問題與不同背景的人來。 –

回答

3

Python並不真的有私有變量,有兩個約定:用下劃線(_var)前綴

  • 變量用來讓你和其他人都知道,它的意圖是私人
  • 變量有兩個undersores(__var)也被Python解釋器錯位以及通過類名稱的前綴爲前綴,但他們還是喜歡self._Superclass__var訪問你的榜樣

另見documentation

你的代碼還有一個問題 - 你正在使用類變量,而不是實例變量(這通常稱爲其他語言中的靜態類變量)。

檢查這個例子:

class Superclass: 
    var = 1 

    def getVar(self): 
     print(self.var) 

my_object = Superclass() 
my_object2 = Superclass() 
my_object.getVar() # outputs 1 
my_object2.getVar() # outputs 1 

Superclass.var = 321 # this value is share across all instances 
my_object.getVar() # outputs 321 
my_object2.getVar() # outputs 321 

而且當你正在做你的方法self.var = xxx任務,你只是隱藏類級變量,並用相同的名字添加新的實例級變量。

另請參閱文檔:https://docs.python.org/3.6/tutorial/classes.html#class-and-instance-variables

+0

由於這些評論的作者沒有寫出我可以選擇的答案,您是否希望將這些信息添加到上面的答案中,以便我可以選擇它?因爲現在,和你的回答一樣有用,它並不完全解決我提出的問題。 –

+1

@ gilberto.agostinho.f好的,我更新了答案。 –