Python OOP
Python Encapsulation
Encapsulation means bundling data with the methods that operate on it, and controlling how much of that data is directly exposed to the outside world.
Public, Protected and Private Attributes
Python uses a naming convention rather than strict access control to signal how an attribute should be used: no underscore means public, a single leading underscore means protected (internal use), and a double leading underscore means private.
class Account:
def __init__(self, owner, balance):
self.owner = owner # public
self._pin = 1234 # protected
self.__balance = balance # private
acc = Account("Neha", 5000)
print(acc.owner)
print(acc._pin)A single underscore (_pin) is only a convention — Python does not stop you from accessing it, it just signals "please treat this as internal."
Name Mangling with __
A double leading underscore triggers name mangling: Python internally renames __balance to _Account__balance, which makes it awkward (though not impossible) to access from outside the class.
print(acc.__balance)AttributeError: 'Account' object has no attribute '__balance'Getters and Setters
To read or update a private attribute safely, define public methods, often called getters and setters, that control access and can add validation.
class Account:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance
def get_balance(self):
return self.__balance
def set_balance(self, amount):
if amount >= 0:
self.__balance = amount
else:
print("Balance cannot be negative")
acc = Account("Neha", 5000)
acc.set_balance(-100)
print(acc.get_balance())| Prefix | Meaning | Example |
|---|---|---|
| none | public — freely accessible | self.owner |
| _single | protected — internal convention | self._pin |
| __double | private — name-mangled | self.__balance |
Python's @property decorator, covered in another topic, offers a cleaner way to write getters and setters that still look like plain attribute access.
