Understand single and double underscores in Python names
Use underscore conventions deliberately, understand class name mangling, and distinguish internal attributes from special methods and pattern wildcards.
A leading single underscore, _name, signals an internal implementation detail by convention. A name such as __name inside a class definition can trigger name mangling to reduce accidental clashes with subclasses. Neither is an access-control boundary.
Mark an internal attribute
class Service:
def __init__(self):
self._cache = {}
service = Service()
print(service._cache) # Accessible, but intended as an implementation detail
Callers can access _cache, but doing so couples them to an internal detail that may change. At module level, names beginning with _ are omitted by default from from module import *; an explicit __all__ can change what is exported.
Avoid accidental subclass name collisions
class Base:
def __init__(self):
self.__state = "base"
class Child(Base):
def __init__(self):
super().__init__()
self.__state = "child"
obj = Child()
print(obj._Base__state) # base
print(obj._Child__state) # child
Within a class definition, identifiers beginning with at least two underscores and not ending with two or more are mangled using the class name. In ordinary cases, __state becomes _ClassName__state. Leading underscores in the class name are stripped when forming that prefix.
Outside the class, obj.__state does not automatically become either of those attributes and normally raises AttributeError. A literal string passed to getattr(obj, "__state") is not automatically rewritten either. Name mangling is a lexical naming mechanism, not hidden storage.
Recognize other forms
| Form | Meaning |
|---|---|
_name |
Conventionally internal |
__name inside a class |
Eligible for name mangling |
__name__ |
A special-name form reserved for Python protocols |
_ in ordinary assignments or loops |
An ordinary name often used for an ignored value |
_ in a match pattern |
A wildcard that does not bind a name |
The interactive interpreter commonly uses _ for the last displayed result; application code and tools may assign it another meaning.
FAQ
Does mangling make an attribute private? No. The mangled name is still accessible. It protects against accidental collisions rather than intentional access.
Should I invent a special method such as foo? Avoid it. That naming space is reserved for language-defined protocols and can conflict with future behavior.
Can a subclass still modify the base attribute? Yes, by intentionally accessing the mangled base name. Its own __state spelling normally creates a separate attribute instead.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan