Encapsulation helps in data protection, ensuring that an object's internal state is hidden from the outside world — a concept known as Data Hiding. This promotes better control, security, and modularity in your Python programs.
What is Encapsulation?
Encapsulation is the mechanism of binding data and code together within a class and restricting direct access to the data from outside the class. Instead, you interact with the data using defined methods (getters, setters, etc.), ensuring controlled modification.Key idea: Protect internal object details and expose only necessary parts through a clean interface.
Example
class Student:
def __init__(self, name, marks):
self.name = name # Public attribute
self.__marks = marks # Private attribute
def get_marks(self): # Getter method
return self.__marks
def set_marks(self, marks): # Setter method
if 0 <= marks <= 100:
self.__marks = marks
else:
print("Invalid marks!")
s1 = Student("Alice", 85)
print(s1.name) # Accessing public member
print(s1.get_marks()) # Accessing private member via getter
s1.set_marks(95)
print(s1.get_marks())
Output:
Alice
85
95
- The private attribute __marks cannot be accessed directly.- Access and modification are done through controlled methods (get_marks and set_marks).
What is Data Hiding?
Data Hiding is the practice of restricting direct access to class attributes and methods to prevent accidental or unauthorized modification. It's an implementation of encapsulation — hiding "how" things work internally.Python achieves data hiding using access modifiers like:
- Public
- Protected
- Private
Access Modifiers in Python
Python doesn't have strict access control like other languages (e.g., Java or C++), but it follows naming conventions to indicate the level of access.| Access Type | Syntax | Accessible From | Description |
|---|---|---|---|
| Public | variable |
Anywhere (inside/outside class) | No restriction on access |
| Protected | _variable |
Within class and subclasses | Conventionally restricted |
| Private | __variable |
Only within the class | Name-mangled to prevent external access |
Public Members
Public members are accessible from anywhere — inside or outside the class.class Car:
def __init__(self, brand, model):
self.brand = brand # Public
self.model = model # Public
c1 = Car("Tesla", "Model S")
print(c1.brand) # Accessible
print(c1.model) # Accessible
- Public members are the default in Python.- They are intended to be openly accessed and modified if needed.
Protected Members
Protected members are prefixed with a single underscore (_). They can still be accessed outside the class, but by convention, they should only be used within the class or its subclasses.class Vehicle:
def __init__(self):
self._speed = 60 # Protected member
class Car(Vehicle):
def show_speed(self):
print("Speed:", self._speed)
c = Car()
c.show_speed()
print(c._speed) # Technically accessible, but not recommended
Output:
Speed: 60
60
- Python doesn't enforce protection strictly — it's a convention indicating internal use.- In larger codebases, this helps developers maintain discipline.
Private Members
Private members are prefixed with double underscores (__). They are name-mangled internally to prevent accidental access from outside the class.class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private attribute
def deposit(self, amount):
self.__balance += amount
def get_balance(self):
return self.__balance
acc = BankAccount(5000)
acc.deposit(1500)
print(acc.get_balance())
# Direct access (will cause an error)
# print(acc.__balance) # AttributeError
Output:
6500
- Attempting to access __balance directly will cause an AttributeError.- Internally, Python renames it to _ClassName__attribute, a process called name mangling.
Name Mangling Example
Name mangling in Python is a mechanism that modifies the names of class attributes (variables and methods) that start with two leading underscores (e.g., __attribute_name).The name mangling process helps to access the class variables from outside the class.
Name mangling does not provide true privacy like private keywords in other languages (e.g., Java, C++). The mangled name can still be accessed directly if you know the convention (e.g., _ClassName__attribute_name).
class Example:
def __init__(self):
self.__secret = "Hidden Value"
obj = Example()
# Accessing via name mangling
print(obj._Example__secret)
Output:
Hidden Value
- Name mangling changes __secret to _Example__secret.- This is possible, but not recommended for regular use — it breaks encapsulation.
Real-World Example: Data Hiding in Practice
This example shows how data hiding protects sensitive information like account balance and number from direct access. Instead, controlled access is provided through public methods such as deposit(), withdraw(), and get_balance().class Bank:
def __init__(self, account_number, balance):
self.__account_number = account_number
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
print(f"Deposited: {amount}")
else:
print("Invalid deposit amount!")
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
print(f"Withdrawn: {amount}")
else:
print("Insufficient balance or invalid amount!")
def get_balance(self):
return self.__balance
b1 = Bank("ACC123", 5000)
b1.deposit(2000)
print("Current Balance:", b1.get_balance())
# Attempt to access private data
# print(b1.__balance) # ❌ Not allowed
Output:
Deposited: 2000
Current Balance: 7000
- Only authorized methods (deposit, withdraw, get_balance) can interact with private data.- This ensures that object data remains consistent and safe.
Getters and Setters in Python
Getters and setters are methods used to access and modify private data safely.class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
if age > 0:
self.__age = age
else:
print("Invalid age!")
p = Person("Alice", 25)
print(p.get_age())
p.set_age(30)
print(p.get_age())
- These methods ensure that invalid data cannot be assigned directly.- They enforce rules on how private data should be modified.
25
30
Summary
Encapsulation and Data Hiding are at the heart of building robust, secure, and maintainable Python applications. They help you design cleaner APIs, protect object integrity, and simplify debugging.| Concept | Description |
|---|---|
| Encapsulation | Wrapping data and methods in a class |
| Data Hiding | Restricting direct access to internal data |
| Public Members | Accessible everywhere |
| Protected Members | Intended for class and subclass use |
| Private Members | Accessible only within the class |
| Name Mangling | Internal renaming of private attributes |
| Getters/Setters | Control data access and modification |
- Use public members for open access.
- Use protected members for subclass extension.
- Use private members for sensitive data.
Together, they form the foundation of information security and object integrity in Python OOP.