In Python, it is a convention to use _var_name
in order to indicate that something is private, but it does not enforce it like in languages as C++, C#, Java, etc.
A double underscore prefix causes the Python interpreter to rewrite the attribute name in order to avoid naming conflicts in subclasses.
This is also called name mangling—the interpreter changes the name of the variable in a way that makes it harder to create collisions when the class is extended later.
Consider the following example
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__baz = 23
Now, let's run the following code:
>>> t = Test()
>>> dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_bar', 'foo']
dir(t)
gives us a list with the object’s attributes. When you search for __baz
in that list you’ll see that there is no variable with that name. If you look closely you’ll see there’s an attribute called _Test__baz
on this object. This is the name mangling that the Python interpreter applies.