Double Underscores and Name Mangling in Python

In Python, prefixing an attribute or method with double leading underscores triggers a mechanism known as name mangling. This process automatically rewrites the identifier's internal name to include the enclosing class name, preventing naming collisions between parent classes and their subclasses during inheritance. While often mistaken for a tool to enforce strict data privacy, name mangling is specifically designed to protect internal state from accidental overrides in complex inheritance hierarchies.

How Name Mangling Works

When the Python interpreter encounters an identifier with at least two leading underscores and at most one trailing underscore (such as __attribute), it internally transforms the name. The identifier is replaced with a single leading underscore, followed by the enclosing class name, followed by the original attribute name:

_ClassName__attribute

For example, an attribute named __data inside a class named Storage is transformed into _Storage__data.

class Storage:
    def __init__(self):
        self.__data = "Confidential"

s = Storage()
# Accessing s.__data directly raises an AttributeError
# print(s.__data) 

# Accessing the mangled name succeeds
print(s._Storage__data)  # Outputs: Confidential

The Primary Goal: Preventing Subclass Collisions

The definitive purpose of name mangling is to avoid name clashes when a class is extended by a subclass. Without name mangling, if a subclass defines an attribute with the same name as a private attribute in the parent class, it inadvertently overwrites the parent's value.

Consider an inheritance scenario:

class Base:
    def __init__(self):
        self.__id = "BASE_101"

    def get_id(self):
        return self.__id

class Derived(Base):
    def __init__(self):
        super().__init__()
        self.__id = "DERIVED_202"

obj = Derived()
print(obj.get_id())  # Outputs: BASE_101
print(obj._Derived__id)  # Outputs: DERIVED_202

Because Base.__id is mangled to _Base__id and Derived.__id is mangled to _Derived__id, both variables coexist on the same instance without interfering with one another.

What Name Mangling Does Not Do

Name mangling is not an access control mechanism like private in C++ or Java. Python adheres to the philosophy that "we are all consenting adults here." Because the mangled name remains accessible from outside the class namespace via _ClassName__attribute, it does not enforce absolute encapsulation or provide security against intentional modification.

When to Use Double Underscores