Encapsulation | Dataplexa

Encapsulation in Python

Encapsulation is one of the core principles of Object-Oriented Programming. It protects the internal data of a class by controlling how it is accessed or modified. This helps build secure, organized, and well-structured programs.

What Is Encapsulation?

Encapsulation refers to wrapping data (variables) and methods (functions) into a single unit — a class. It restricts direct access to certain components, preventing accidental modifications. This ensures your program behaves in a predictable and safe way.

Why Use Encapsulation?

Encapsulation helps maintain data integrity inside objects. It allows developers to hide unnecessary implementation details and expose only what is needed. This provides control, security, and a cleaner interface for interacting with objects.

Types of Encapsulation in Python

Python provides three main levels of access control: Public, Protected, and Private. Although Python uses naming conventions instead of strict rules, these conventions are widely followed.

1. Public Members

Public variables and methods can be accessed freely from anywhere. Most class attributes are public by default unless specified otherwise.

class Person:
    def __init__(self):
        self.name = "Alex"   # public

p = Person()
print(p.name)

2. Protected Members

Protected members use a single underscore prefix (_value). They indicate that the attribute is intended for internal use, but still accessible if needed.

class Person:
    def __init__(self):
        self._age = 25   # protected

p = Person()
print(p._age)

Protected variables should be used carefully but are not strictly hidden.

3. Private Members

Private members use a double underscore prefix (__value). They cannot be accessed directly from outside the class, making them useful for sensitive data.

class Person:
    def __init__(self):
        self.__salary = 5000  # private

p = Person()
# print(p.__salary)  # Error

Private attributes can only be accessed through special methods inside the class.

Getter and Setter Methods

Getters allow you to read private data, while setters allow controlled updates. This ensures that values change only when rules are followed, improving data safety.

class BankAccount:
    def __init__(self):
        self.__balance = 1000

    def get_balance(self):
        return self.__balance

    def set_balance(self, amount):
        if amount > 0:
            self.__balance = amount

acct = BankAccount()
print(acct.get_balance())

Setters help prevent invalid updates, such as negative amounts.

Name Mangling

Private variables are internally renamed using name mangling. This prevents accidental access while still making testing and debugging possible.

class Demo:
    def __init__(self):
        self.__value = 10

d = Demo()
print(d._Demo__value)   # accessing private using name mangling

Although name mangling allows access, it should be used only when necessary.

Real-World Example

Encapsulation is widely used in financial systems, software security, and user-data protection. It ensures sensitive information like passwords, balances, and personal details stay controlled.

class User:
    def __init__(self, password):
        self.__password = password

    def verify(self, pwd):
        return pwd == self.__password

u = User("secret123")
print(u.verify("secret123"))

📝 Practice Exercises


Exercise 1

Create a class Laptop with a private attribute __price and methods to get and update the price.

Exercise 2

Create a class Student with a protected attribute _grade and print it through an object.

Exercise 3

Write a class with private data and demonstrate name mangling.

Exercise 4

Create a class Account that restricts setting a negative balance using a setter method.


✅ Practice Answers


Answer 1

class Laptop:
    def __init__(self, price):
        self.__price = price

    def get_price(self):
        return self.__price

    def set_price(self, value):
        if value > 0:
            self.__price = value

l = Laptop(1200)
print(l.get_price())

Answer 2

class Student:
    def __init__(self, grade):
        self._grade = grade

s = Student("A")
print(s._grade)

Answer 3

class Demo:
    def __init__(self):
        self.__value = 50

d = Demo()
print(d._Demo__value)

Answer 4

class Account:
    def __init__(self, balance):
        self.__balance = balance

    def set_balance(self, amt):
        if amt >= 0:
            self.__balance = amt

    def get_balance(self):
        return self.__balance

acc = Account(500)
acc.set_balance(300)
print(acc.get_balance())