关于python:类和私有变量

class and private variables

1
2
3
4
5
6
7
8
9
10
11
12
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将自动重命名为_Foo__bar,因此Test1中的__test_Test1__testTest2中的_Test2__test。这两个成员实际上是不同的。这是为了"避免名称与子类定义的名称冲突"而设计的。

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


这种行为是由于用EDCOX1 OR 9来开始的属性名称的命名。基本上,__test在EDCOX1×4内和EDCOX1×7内被EDCOX1〔5〕纠缠在一起,因此它们是两个不同的属性。


它在其他语言中也有同样的作用,比如Java(试试它!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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语言中都不起作用"和"这就是为什么你不为私有变量使用名字过滤"——Java与Python相比采取了另一种面向对象的方法,并且不为私有变量使用名字过滤,但行为是相同的。

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

只有当test2为getValue()声明自己的实现时,test1的私有成员才变得不可访问,test2的私有成员才变得可访问。

换句话说,可以说私有成员不是"虚拟的"(或"可重写的")。它们是类及其方法的实现细节,不应该被重写。Test1.__testTest2.__test是不同的实例变量(通过名称管理在python中实现)。

如果您希望传统的OO行为,其中子类成员重写其父级,则使用Python、Java或C++中的一种虚拟方法,即C *、Delphi;而不是私有属性。如果要实现没有名称冲突的内容,请使用私有属性。