Does Python have "private" variables in classes?
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.
Introduction
Python does not have true private variables like Java, C++, or C#. Instead, it uses naming conventions and a mechanism called name mangling to indicate that certain attributes should not be accessed directly. Python's philosophy is "we are all consenting adults" — it trusts developers to follow conventions rather than enforcing access restrictions.
The Three Levels of Access
Public: name
No underscore prefix. Intended for external use:
Protected (Convention): _name
Single underscore prefix. Signals "for internal use" but is not enforced:
The single underscore is a widely respected convention. Linters and IDEs may warn when accessing _ prefixed attributes from outside the class, but Python does not prevent it.
"Private" (Name Mangling): __name
Double underscore prefix triggers name mangling — Python renames the attribute to _ClassName__name:
Name mangling makes accidental access harder but does not truly prevent it. Its primary purpose is to avoid name collisions in inheritance hierarchies, not to enforce privacy.
Name Mangling in Detail
Python transforms __attribute to _ClassName__attribute at compile time:
Without name mangling, both self.__value assignments would overwrite each other. Name mangling keeps them separate.
Using @property for Controlled Access
The Pythonic way to control attribute access is the @property decorator:
With Getter and Setter
Comparison with Other Languages
| Language | Mechanism | Enforced? |
| Python | _ convention, __ name mangling | No (convention-based) |
| Java | private keyword | Yes (compile-time, but reflection bypasses) |
| C++ | private: section | Yes (compile-time) |
| C# | private keyword | Yes (compile-time, but reflection bypasses) |
| JavaScript | # prefix (ES2022) | Yes (runtime enforcement) |
| Ruby | private method | Yes (but send() bypasses) |
Even in languages with "true" private access, reflection or other mechanisms can often bypass it. Python simply makes this explicit rather than pretending privacy is absolute.
__slots__ for Attribute Restriction
If you want to prevent adding arbitrary attributes to a class, use __slots__:
__slots__ restricts which attributes can exist, but does not control read/write access.
Common Pitfalls
- Trust the Convention: When working in a team, respect the underscore conventions as a contract regarding intended use. Accessing
_internalattributes from outside the class makes your code fragile — internal APIs can change without warning. - Use Properties: Instead of relying purely on name mangling, use
@propertyto manage attribute access. Properties provide validation, computed values, and clear interfaces. - Dunder confusion: Attributes with double underscores on both sides (
__init__,__str__) are Python's special methods (dunder methods), not private attributes. Do not use double leading and trailing underscores for your own attributes. - Serialization: Name-mangled attributes can cause issues with
pickle,json, and other serialization libraries that inspect attribute names. Prefer single-underscore convention for attributes that need to be serialized. - Testing: Name mangling makes unit testing harder because tests outside the class must use
_ClassName__attr. This is another reason to prefer_single_underscoreand@property.
Summary
- Python has no true
privatekeyword — access control is by convention _name: "protected" convention — internal use, not enforced__name: name mangling to_ClassName__name— avoids name collisions in inheritance- Use
@propertyfor controlled, validated access to attributes - Follow the conventions — they are the social contract of Python development
Related reading
- Domain events with composite pattern
- Double Checked Locking in Singleton
- DTO and DAO concepts and MVC
- Enterprise Library Unity vs Other IoC Containers
- Does Python optimize tail recursion?
- Does Python support multithreading? Can it speed up execution time?
- Enum Inheritance
- Examples of GoF Design Patterns in Java's core libraries

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.