Encapsulation

3 min read

The Art of Data Hiding & Protection

What is Encapsulation? #

Encapsulation is all about bundling the data (attributes) and methods (functions) that work on that data into a single unit — the class — and then restricting direct access to some of the object’s components.

Think of it like this:

  • You have a smartphone.
  • You use its apps, camera, and calls — but you don’t (and shouldn’t have to) mess with the internal hardware or software directly.
  • Encapsulation is like putting a protective shell around your object’s data and methods so they don’t get accidentally changed or misused by outside code.

Why Encapsulation? #

  • Protect your data from accidental modification.
  • Control how the data is accessed or updated.
  • Improve code maintainability by hiding complexity.
  • Make the interface clean and simple — users interact only with public methods.

Encapsulation in Real Life #

Imagine a bank account:

  • You can deposit or withdraw money.
  • But you don’t get to change the account balance directly.
  • The bank’s system hides the internal balance and only exposes deposit/withdraw functions.
  • This prevents you from accidentally setting the balance to a wrong number.

How Does Python Implement Encapsulation? #

Python does encapsulation differently than languages like Java or C++:

  • It doesn’t enforce strict private/public access modifiers.
  • Instead, Python uses naming conventions to indicate privacy.
  • You still can access “private” attributes if you want, but by convention, you shouldn’t.

Access Modifiers in Python (By Convention) #

ModifierHow to Use ItMeaningExample
PublicNormal namesFully accessibleself.name
ProtectedPrefix with single _Internal use only (convention)self._balance
PrivatePrefix with double __Name mangled to prevent accidental accessself.__pin

What’s Name Mangling? #

When you prefix an attribute with double underscores __, Python internally changes the name to _ClassName__attributeName. This makes it harder (but not impossible) to access from outside.


Example: Encapsulation in Python #

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner          # Public attribute
        self.__balance = balance    # Private attribute

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"Deposited {amount}. New balance: {self.__balance}")
        else:
            print("Deposit amount must be positive.")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"Withdrawn {amount}. New balance: {self.__balance}")
        else:
            print("Insufficient funds or invalid amount.")

    def get_balance(self):
        return self.__balance

Using the Class: #

account = BankAccount("Hannan", 1000)

print(account.owner)          # Hannan (public)
print(account.get_balance())  # 1000

account.deposit(500)          # Deposited 500. New balance: 1500
account.withdraw(200)         # Withdrawn 200. New balance: 1300

# Trying to access private attribute directly:
print(account.__balance)      # Error! AttributeError

# But can still access with name mangling (not recommended):
print(account._BankAccount__balance)  # 1300 (discouraged)

Why Not Just Make Everything Public? #

You could just let users access attributes directly, like account.balance = 1000000, but then:

  • There’s no control or validation.
  • Your data can become inconsistent or corrupted.
  • Harder to maintain or debug later.

How to Use Getters and Setters in Python? #

Instead of exposing attributes directly, you can use getter and setter methods to control access.

class BankAccount:
    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.")

But Python’s property decorator makes this smoother:

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

    @property
    def balance(self):
        return self.__balance

    @balance.setter
    def balance(self, amount):
        if amount >= 0:
            self.__balance = amount
        else:
            print("Balance cannot be negative.")

Usage:

account = BankAccount("Hannan", 1000)
print(account.balance)    # 1000
account.balance = 5000    # sets new balance
account.balance = -100    # Balance cannot be negative.

Encapsulation Best Practices #

  • Use single underscore _ for “protected” attributes, meaning “use with care, internal to the class and its subclasses.”
  • Use double underscore __ for attributes you want to strongly discourage outside access.
  • Use properties (@property) to provide controlled access to attributes.
  • Avoid exposing attributes directly; use methods or properties.
  • Keep your class interface simple and intuitive.
  • Document your class and methods well so users know what’s safe to use.

Real-World Use Case: Employee Data Protection System #

Imagine a company system storing employee salary data. You want to keep salary info private and only allow HR managers to update it.

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.__salary = salary

    @property
    def salary(self):
        return self.__salary

    @salary.setter
    def salary(self, value):
        if value > 0:
            self.__salary = value
        else:
            print("Invalid salary amount.")

This way, no one outside can set a negative salary or arbitrarily change it without validation.


Summary: Why Encapsulation is Essential #

  • It protects your data and keeps your objects safe from unintended interference.
  • It provides a clean and controlled interface for interacting with your objects.
  • It helps maintain code integrity and consistency.
  • It enables you to change internal implementation without affecting external code.

When you use encapsulation properly, your programs become more robust, secure, and easier to maintain.


What’s Next? #

Ready to explore Abstraction, the next pillar, where we learn how to simplify complex systems and show only necessary details? Or want me to add more examples or exercises on Encapsulation first? Let me know!

Updated on June 9, 2025