Encapsulation
16 min
Encapsulation means controlling how an object's internal state can be
read or changed — instead of letting any code reach in and set
account.balance = -500 directly, you expose a controlled interface
(methods, or a @property) that can enforce rules.
Python doesn't have true "private" attributes, but the convention
_balance (leading underscore) signals "internal, don't touch directly
from outside" even though nothing technically stops you:
class BankAccount:
def __init__(self, balance=0):
self._balance = balance # "private by convention"
@property
def balance(self):
return self._balance # read-only access from outside
@property makes balance READABLE like a plain attribute (account.balance, not account.balance()) while still being a method under the hood -- and since there's no matching setter, it's read-only from outside the class.
The real value of encapsulation shows up in a method that VALIDATES before changing state — logic a raw public attribute could never enforce:
def withdraw(self, amount):
if amount > self._balance or amount < 0:
return False # reject, state unchanged
self._balance -= amount
return True
If balance were just a plain public attribute, nothing would stop
account.balance -= 999999, overdrawing the account with no validation
at all. Routing every change through a method (or a @property setter)
means the "can never go negative" rule lives in exactly ONE place,
guaranteed to run every single time the balance changes.
Given `BankAccount` below, implement the `balance` property getter (`@property def balance(self)`), returning `self._balance`.
Implement `withdraw(self, amount)`: if `amount` is negative or greater than the current balance, return False without changing anything. Otherwise subtract it from the balance and return True.
What is 'encapsulation' in OOP?
You can expose read-only access to internal state via @property, and enforce validation rules on state changes through methods instead of a raw public attribute.