Question
In Python, what do single and double leading underscores before an object's name mean?
For example, what is the difference between names such as:
_name
__name
How does Python treat these names, and what do they communicate to other developers?
Short Answer
By the end of this page, you will understand what leading underscores mean in Python, the difference between _name and __name, when Python applies name mangling, and how these naming styles are used in real code to signal intent and avoid accidental misuse.
Concept
In Python, leading underscores in names are mainly about convention and intent.
Single leading underscore: _name
A single leading underscore usually means:
- "This is internal"
- "This is meant for use inside this module or class"
- "You can access it, but you probably should not unless you know what you are doing"
Python does not make _name truly private. It is only a naming convention.
Example:
class User:
def __init__(self):
self._token = "secret"
You can still do this:
user = User()
print(user._token)
That works. The underscore is a signal to developers, not a hard restriction.
A single leading underscore also matters for from module import *. By default, names starting with _ are not imported.
Double leading underscore: __name
A double leading underscore inside a class triggers name mangling.
Python changes the name internally to reduce accidental access or accidental overriding in subclasses.
Example:
Mental Model
Think of Python names like rooms in a building.
nameis a public room with an open door._nameis a room with a sign saying staff only. The door is not locked, but people are expected to respect the sign.__nameis a room whose label is changed behind the scenes, so it is harder to walk into by accident.
The important idea is that Python prefers trust and convention over strict access control. Instead of blocking access completely, it gives signals about what should and should not be used directly.
Syntax and Examples
Basic syntax
class Example:
def __init__(self):
self.public = 1
self._internal = 2
self.__mangled = 3
Accessing each attribute
obj = Example()
print(obj.public) # 1
print(obj._internal) # 2
# print(obj.__mangled) # AttributeError
print(obj._Example__mangled) # 3
What this means
publicis meant to be used freely._internalis a non-public attribute by convention.__mangledis name-mangled by Python.
Example with inheritance
class Parent:
def __init__(self):
._value =
.__secret =
():
():
().__init__()
.__secret =
child = Child()
(child._value)
(child._Parent__secret)
(child._Child__secret)
Step by Step Execution
Consider this example:
class Account:
def __init__(self):
self._balance = 100
self.__pin = 4321
account = Account()
print(account._balance)
print(account._Account__pin)
Step by step
- Python starts defining the
Accountclass. - Inside
__init__, two instance attributes are assigned. self._balance = 100- Python stores an attribute literally named
_balance. - No special transformation happens.
- Python stores an attribute literally named
self.__pin = 4321- Because it starts with two underscores and is inside a class, Python mangles the name.
- Internally, it becomes
_Account__pin.
account = Account()creates an instance and runs__init__.print(account._balance)works because_balanceexists with that exact name.
Real World Use Cases
1. Marking internal helper methods
Libraries often use a single underscore for methods that are not part of the public API.
class Parser:
def parse(self, text):
return self._clean(text)
def _clean(self, text):
return text.strip().lower()
Here, parse() is public, while _clean() is an internal implementation detail.
2. Avoiding subclass name collisions
Double underscores are useful when a base class wants to protect an internal attribute from being accidentally replaced by a subclass.
class BaseLogger:
def __init__(self):
self.__prefix = "LOG"
A subclass can define its own __prefix without overwriting the base class's version.
3. Hiding module internals from wildcard imports
In modules, names with a single leading underscore are treated as non-public.
Real Codebase Usage
In real projects, underscores are used as part of API design.
Public vs internal attributes
Developers commonly separate names like this:
class ReportService:
def generate(self):
data = self._fetch_data()
return self._format(data)
def _fetch_data(self):
return [1, 2, 3]
def _format(self, data):
return ", ".join(str(x) for x in data)
The public method is generate(). The underscored methods support it internally.
Guarding against accidental overrides
In frameworks and large class hierarchies, double underscores may be used when a base class must keep an internal attribute separate.
class Base:
def __init__():
.__state = {}
Common Mistakes
Mistake 1: Thinking _name is private
Broken assumption:
class Demo:
def __init__(self):
self._value = 10
obj = Demo()
print(obj._value) # This works
A single underscore does not block access. It only signals internal use.
Mistake 2: Thinking __name means true privacy
class Demo:
def __init__(self):
self.__value = 10
obj = Demo()
print(obj._Demo__value) # Still accessible
Double underscores use name mangling, not true private access control.
Mistake 3: Overusing double underscores
Many beginners use __name everywhere. That often makes code harder to debug and extend.
Use double underscores only when you specifically want to avoid name collisions in subclasses.
Mistake 4: Forgetting name mangling only applies inside classes
Comparisons
| Name style | Example | Meaning | Enforced by Python? | Common use |
|---|---|---|---|---|
| Public | name | Intended for normal use | No restriction needed | Public API |
| Single leading underscore | _name | Internal by convention | No | Internal helpers, non-public attributes |
| Double leading underscore | __name | Name-mangled in classes | Partly, via renaming | Avoiding subclass collisions |
| Double leading and trailing underscore | __init__ | Special Python-defined name |
Cheat Sheet
Quick rules
name→ public_name→ internal by convention__name→ name-mangled inside classes__name__→ special Python-defined name
Examples
class Example:
def __init__(self):
self.value = 1
self._value = 2
self.__value = 3
Access:
obj = Example()
print(obj.value) # works
print(obj._value) # works
print(obj._Example__value) # works
# print(obj.__value) # AttributeError
Key facts
- Single underscore is a convention, not privacy.
- Double underscore triggers name mangling in classes.
- Name mangling helps avoid accidental collisions in subclasses.
- Double underscore on both sides, like
__init__, is a special method name, not a private name.
FAQ
Is _variable private in Python?
No. It is only a convention that says the name is internal and should not usually be accessed directly.
Is __variable truly private?
No. Python mangles the name, but it can still be accessed using its mangled form, such as _ClassName__variable.
Why does Python use conventions instead of strict private members?
Python emphasizes readability, trust, and developer responsibility. Conventions are often enough and keep the language flexible.
What is name mangling in Python?
Name mangling is when Python rewrites a class attribute like __value to something like _ClassName__value to avoid accidental name collisions.
Should I use double underscores for all internal attributes?
Usually no. Most internal attributes should use a single underscore. Double underscores are mainly useful when inheritance could cause collisions.
Is __init__ the same as __value?
No. __init__ is a special built-in method name with meaning defined by Python. __value is a regular name that gets mangled inside a class.
Why is _name skipped in from module import *?
Mini Project
Description
Create a small Python class that demonstrates public, internal, and name-mangled attributes. This project helps you see how underscore naming affects access, readability, and inheritance in practical code.
Goal
Build a class and subclass that show the difference between name, _name, and __name in action.
Requirements
- Create a base class with one public, one single-underscore, and one double-underscore attribute.
- Add a method that prints the values from inside the class.
- Create a subclass that defines its own double-underscore attribute with the same name.
- Instantiate the subclass and show which attributes are accessible from outside.
- Demonstrate the mangled names for both base and subclass attributes.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.
Catch Multiple Exceptions in One except Block in Python
Learn how to catch multiple exceptions in one Python except block using tuples, with examples, mistakes, and real-world usage.