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: ConfidentialThe 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_202Because 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
- Use a single underscore (
_attribute): For general internal use. A single leading underscore is the Pythonic convention to signal to other developers that an attribute or method is private and not intended for external use. - Use double underscores (
__attribute): Only when designing classes intended for inheritance where an attribute must remain unshadowed by subclasses, or to prevent unintended method overriding in deep class hierarchies.