Python encapsulation and properties
Keep validation next to the state it protects.
On this page
Classes and exceptions.
- Keep validation next to the state it protects.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
Encapsulation groups state with operations that maintain its rules. This account stores nonnegative integer units and rejects nonpositive deposits.
A read-only property exposes the balance through the public interface. A leading underscore is a convention for internal use, not enforced private access or a security boundary.
Code example
class Account:
def __init__(self):
self._balance = 0
@property
def balance(self):
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("deposit must be positive")
self._balance += amount
account = Account()
account.deposit(25)
print(account.balance)
try:
account.deposit(0)
except ValueError:
print("Rejected")
assert account.balance == 2525 Rejected
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
class Account: def __init__(self): self._balance = 0 @property def balance(self): return self._balance def deposit(self, amount): if amount <= 0: raise ValueError("deposit must be positive") self._balance += amount account = Account()account.deposit(25)print(account.balance)try: account.deposit(0)except ValueError: print("Rejected")assert account.balance == 25Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Initialize the balance. | balance = 0 | — | |
| Pass a positive amount. | amount = 25 | — | |
| Add the deposit. | balance = 25 | — | |
| Read through the property. | balance = 25 | 25 | |
| Try a zero deposit. | amount = 0 | 25 | |
| Reject it before changing state. | balance = 25 | 25 | |
| The caller handles the expected error. | balance = 25 | 25 Rejected |
Behind the scenes
How Python processes this code
Python runs this source through its interpreter. It creates objects for values and resolves names as each statement runs.
Cost and common mistakes
O(1) work and space per bounded deposit.
- Do not bypass validation by assigning internal state directly.
- This teaching account omits persistence, concurrency, and currency rounding.
Try it yourself
Try a deposit of -5 and then check the balance.
Reveal answer and reasoning
It raises ValueError and the balance remains 25.