consider the following code:
class animal:
def __init__(self, name):
self.__name = name
class dog(animal):
def __init__(self, owner, name):
self.__owner = owner
super(dog, self).__init__(name)
terrier = dog('A', 'B')
terrier.owner = 'C'
terrier.name = 'D'
print(terrier._dog__owner, terrier._animal__name)
print(terrier.owner, terrier.name)
The output is:
A B
C D
I understand that Python private variables are only protected by convention. But all other threads mention ._className__attributeName eg. terrier._dog__owner as the only way of altering variable values. Here I am able to alter them even using terrier.owner or terrier.name.
Strangely, both give a different output as shown above. So do terrier.owner or terrier.name create different instances from terrier._dog__name or terrier._animal__name? What exactly has happened here?
Double-underscore variables are indeed not private the way Java or C++ see privacy. They are not meant to be seen as private to code outside the class. They are used to avoid name clashes among subclasses, which is why the classname is used as a prefix.
E.g. when you have an internal implementation for a class Foo
, and you don't want the subclass Bar(Foo)
to accidentally use the same names in their implementation, you can use the attribute __spam
, which will be transformed to _Foo__spam
and _Bar__spam
respectively, and thus won't clash.
The terrier.owner
and terrier.name
attributes you added are independent and have nothing to do with the _dog__owner
and _animal__name
attributes used by your classes. Using double-underscore variable names does not prevent other attributes from being created, including the same name without underscores.