类和私有变量

时间:2011-05-31 11:55:24

标签: python

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()

为什么打印test.getvalue()会返回1?

3 个答案:

答案 0 :(得分:9)

在Python中,类__bar的私有成员Foo将为automatically renamed_Foo__bar,因此__test中的Test1为{{ 1}}和_Test1__test中的Test2_Test2__test。这两个成员实际上是不同的。这是按设计,到"avoid name clashes of names with names defined by subclasses"

如果您希望子类看到变量,同时仍希望它不是公共接口的一部分,请使用单个下划线_test

答案 1 :(得分:6)

此行为是由name mangling for attribute names starting with __引起的。基本上,__test_Test1__test内变为Test1,在_Test2__test内变为Test2,因此它们是两个不同的属性。

答案 2 :(得分:1)

它在其他语言中的工作方式完全相同,例如Java(试一试!)

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());
    }
}

(为什么我在Python相关问题中发布Java代码?因为有些评论说“这不适用于任何OO语言”和“这就是为什么你不使用名称修改为私有变量“ - 与Python相比,Java采用另一种方法来处理OO,并且不对私有变量使用名称修改,但行为是相同的)

Test1中声明的方法可以访问Test1的私有变量。除非子类重写该方法,否则从子类调用该方法不会更改任何内容。这并不是私人成员在子类中“消失”或“被覆盖”。它们仍然存在,可以通过父类的方法访问。

只有当Test2为getvalue()声明自己的实现时,Test1的私有成员才会变得不可访问,并且Test2的私有成员将变得可访问。

换句话说,可以说私人成员不是“虚拟的”(或“可覆盖的”)。它们是类及其方法的实现细节,不应该被覆盖。 Test1.__testTest2.__test是不同的实例变量(通过名称修改在Python中实现)。

如果您想要传统的OO行为,其中子类成员会覆盖其父类,请在C ++中使用Python,Java或虚方法中的方法,C# ,德尔福; 私有属性。如果你想实现没有名字冲突的东西,那么使用私有属性。