class Test1: def __init__(self): self.__test = 1 def getvalue(self): return self.__test class Test2(Test1): def __init__(self): Test1.__init__(self) self.__test = 2 test = Test2()
爲什麼print test.getvalue()返回1?類和私有變量
class Test1: def __init__(self): self.__test = 1 def getvalue(self): return self.__test class Test2(Test1): def __init__(self): Test1.__init__(self) self.__test = 2 test = Test2()
爲什麼print test.getvalue()返回1?類和私有變量
在Python,私有成員Foo
類的__bar
將automatically renamed到_Foo__bar
,所以在Test1
的__test
是_Test1__test
並且在Test2
是_Test2__test
。這兩位成員實際上是不同的。這是設計,到"avoid name clashes of names with names defined by subclasses"。
如果您希望子類能夠看到變量,同時仍然不想將其保留爲公共接口的一部分,請使用單個下劃線_test
。
此行爲歸因於name mangling for attribute names starting with __
。基本上,__test
內部Test1
內_Test1__test
和_Test2__test
內部Test2
,所以它們是兩個不同的屬性。
它的工作原理完全一樣的方式在其他語言,比如Java(試試吧!)在Python相關問題
class Test1 {
private int test = 1;
public int getValue() {
return test;
}
}
class Test2 extends Test1 {
private int test = 2;
}
public class Test { // Run the test
public static void main(String[] args) {
Test2 t = new Test2();
System.out.println(t.getValue());
}
}
(爲什麼我張貼的Java代碼呢?因爲一些評論說「這在任何OO語言中都不起作用「,」這就是爲什麼你不用私有變量使用名稱修飾「 - 與Python相比,Java採用另一種OO方法,並且不使用名稱修飾來實現私有變量行爲是相同的)
在Test1中聲明的方法可以訪問Test1的專用變量ES。該方法是否從子類調用不會改變任何內容,除非子類覆蓋該方法。並不是私人成員在兒童班中「消失」或「被忽略」。他們仍然存在,可以通過父類的方法訪問。
只有當Test2爲getvalue()聲明自己的實現時,Test1的私有成員將變得不可訪問,並且Test2的私有成員將變爲可訪問。
換句話說,可以說私人成員不是「虛擬的」(或「可覆蓋的」)。它們是類和它的方法的實現細節,不應該被覆蓋。 Test1.__test
和Test2.__test
是不同的實例變量(通過名稱修改在Python中實現)。
如果你想在傳統的面向對象的行爲,其中一個子類成員重寫其母公司,在Python,Java的使用方法,或虛方法在C++,C#,Delphi的; 不是私有屬性。如果你想實現沒有名字衝突的事情,那麼使用私有屬性。
這不適用於任何OO語言。如果'Test1'有一個私有變量,'Test2'不能訪問它。受保護的變量對其他類隱藏,但暴露給子類。 – unholysampler 2011-05-31 12:04:00
而這**是爲什麼你不使用名稱修改私有變量。 – delnan 2011-05-31 14:44:39