Foundations — Encapsulation — hiding internal state, name mangling (`__name`)
This page assumes you have seen none of the words in the parent note. We build each one, in order, so that by the end you can read OOP Fundamentals and the parent note without hitting an undefined term.
1. What is a "class"? What is an "object"?
The picture: think of a stamp and the ink marks it makes. The stamp is the class; each mark on paper is an object.

Why the topic needs it: encapsulation is about hiding the internals of an object. You cannot talk about "internal state" until you know that an object is a container that has state. This is the foundation everything sits on. It leads into Abstraction — hiding complexity behind interfaces.
2. What is an "attribute"? (the data inside)
The picture: an object is a small filing cabinet; each attribute is a drawer with a label written on the front (balance, celsius) and a value inside (100, -40).
Example, in words: an Account object has an attribute balance holding the number 100. Reading it is account.balance; that dot means "go into this object and find the drawer named balance."
Why the topic needs it: the "internal state" we want to hide is the set of attributes. Name mangling is entirely about how the label on a drawer gets rewritten, so we must first know what a labelled drawer is.
3. What is a "method"? (the buttons)
The picture: on the front of the filing cabinet sit labelled buttons. Pressing deposit(50) is a controlled action the cabinet performs on its own balance drawer. You never open the drawer yourself — you press the button and the cabinet does it.
account.deposit(50) # press the button; the object edits its own drawerWhy the topic needs it: encapsulation = data + methods bundled together, with methods as the only proper way in. The whole "interface vs internal" idea (a vending machine's buttons vs its coin box) is the split between methods (buttons) and attributes (drawers).
4. What is self? (the object talking about itself)
The picture: if the cabinet could talk, self is it pointing at itself and saying "my own balance drawer," written self.balance. If you own three cabinets and press deposit on the second one, self means that second cabinet only.
Why the topic needs it: every private attribute in the parent note is written self.__balance. To understand mangling you must first read self.__balance correctly as "the __balance drawer belonging to this object."
5. What is the underscore character _?
We now have to distinguish four underscore patterns, because the parent note's entire mangling rule is about counting underscores at the front and back.

Why the topic needs it: these four cases are the parent's whole "HOW Python signals private" table. Counting leading vs trailing underscores decides which rule applies.
6. What is __init__? (the setup button)
The picture: the factory line that stamps a fresh cabinet and immediately writes the starting labels and values into its drawers, before you ever touch it.
class Account:
def __init__(self, balance):
self.__balance = 0 # create the drawer, set it to 0Why the topic needs it: every worked example creates its private state inside __init__. Also — carefully — __init__ has two trailing underscores, so it is a dunder and is NOT mangled. This is exactly the "__init__ gets mangled too" myth the parent debunks.
7. What is "invalid state" and an "invariant"?
The picture: a fuel gauge that must live between Empty and Full. If someone reaches in and jams the needle below Empty, the gauge is now lying — an invalid state. The point of hiding the needle is so only the fuel-pump button can move it, keeping the rule true.
Why the topic needs it: "hiding internal state" only matters because it lets the object guard its invariants. Without this idea, hiding would look pointless.
8. What is "name mangling"? (Python rewriting the label)
Now every prerequisite is in place, so we can state the one real mechanism.
The picture: you write __balance on a drawer, but a machine at the factory secretly relabels it _Account__balance before shipping. Any code inside the blueprint that says __balance is also relabelled the same way, so it still finds the drawer. Code outside that types __balance finds nothing.

Why it exists (not security!): if a Base class and a Child class both invent __data, mangling turns them into _Base__data and _Child__data — two different labels — so they never overwrite each other. This is collision avoidance, and it directly supports Inheritance — base and derived classes.
9. Two ways to control access (preview)
- Name mangling (
__name) → avoids clashes; not a lock. - Properties (
@property) → the Pythonic way to run a check every time an attribute is read or written. Built fully in Properties and Descriptors.
Contrast with other languages: Java has a real private keyword the compiler enforces — see Access Modifiers (Java vs Python). Python instead trusts the programmer ("we're all consenting adults").
Prerequisite map
Equipment checklist
Cover the right side and test yourself before reading the parent note.
A class is a
An attribute is
A method is
self means
_name (one underscore) signals
__name (two leading, ≤1 trailing) triggers
_ClassName__name.