class Test1: def __init__( self ): self.__test = 1 def getvalue( self ): return self.__test class Test2( Test1 ): def __init__( self ): T
This behaviour is due to the name mangling for attribute names starting with __. Basically, __test
gets mangled to _Test1__test
inside Test1
and to _Test2__test
inside Test2
, so they are two different attributes.
In Python, private member __bar
of class Foo
will be automatically renamed to _Foo__bar
, so the __test
in Test1
is _Test1__test
and that in Test2
is _Test2__test
. The two members are actually different. This is by design, to "avoid name clashes of names with names defined by subclasses".
Use a single underscore _test
if you want the subclass to see the variable while still want to keep it not part of the public interface.
It works exactly the same way in other languages, such as Java (try it!)
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());
}
}
(Why am I posting Java code in a Python-related question? Because some comments say that “this wouldn't work in any OO language” and “this is why you don't use name mangling for private variables” — Java takes another approach to OO compared to Python, and doesn't use name-mangling for private variables, yet the behavior is the same)
A method declared in Test1 has access to Test1's private variables. Whether the method is called from a child class won't change anything, unless the child class overrides the method. It's not that private members “disappear” or are “overridden” in child classes. They are still there, and can be accessed by methods of the parent class.
Only when Test2 declares its own implementation for getvalue(), then Test1's private members would become inaccessible and Test2's private members would become accessible.
In other words, one could say that private members are not “virtual” (or “overridable”). They are the implementation details of the class and its methods, and are not supposed to be overridden. Test1.__test
and Test2.__test
are different instance variables (implemented in Python by name-mangling).
If you want the traditional OO behaviour, where a child class member overrides its parent, use a method in Python, Java, or a virtual method in C++, C#, Delphi; not private attributes. If you want to implement something without name clashes, then use private attributes.