Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Encapsulation

Protect important state, expose only safe actions, and keep business rules close to the data they govern.

Encapsulation means an object owns its rules. Other code can request changes, but it should not be able to break the object’s internal state by accident.


Why This Matters in Business Software

A pricing object should not allow a negative price. A payroll object should not let random code overwrite tax totals. A bank account should not let any caller directly assign a fake balance.

Encapsulation helps you:

  • protect sensitive values such as balances, discounts, and permissions

  • centralize validation in one place instead of scattering if checks everywhere

  • reduce bugs caused by direct attribute mutation

  • create APIs that are easier for teams to understand and trust

Learning Goals

By the end of this notebook, you should be able to:

  • explain the difference between internal state and public behavior

  • use methods and properties to validate updates safely

  • describe Python naming conventions for public, protected, and private-like attributes

  • connect encapsulation to inheritance and polymorphism

Core Idea

Encapsulation does not mean hiding everything. It means designing deliberate access.

Design choiceMeaning in PythonTypical use
balancepublic attributesimple data that callers may read or update directly
_balanceinternal-by-conventioninternal detail that should be handled carefully
__balancename-mangled private-like attributestate accessed through methods or properties

Visual Intuition

Caption: External code should request changes through methods. The object decides whether the change is valid before touching its internal state.*

Worked Example: Protecting an Account Balance

The real protection is not the double underscore alone. The real protection is that every update goes through a method where the validation lives.

class Product:
    def __init__(self, name, price):
        self.name = name
        self._price = 0
        self.price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError('Price cannot be negative')
        self._price = round(value, 2)

    def apply_discount(self, percent):
        if not 0 <= percent <= 100:
            raise ValueError('Discount must be between 0 and 100')
        self.price = self.price * (1 - percent / 100)

product = Product('Analytics Dashboard License', 249.99)
product.apply_discount(15)
print(product.name, product.price)

Guided Practice

Quick MCQ

Which statement best captures encapsulation?

  • A) Put all data in global variables so every function can access it

  • B) Bundle data with methods and control how state changes

  • C) Only use inheritance when writing classes

Correct answer: B

Reflection Questions

  1. Why is balance exposed as a property instead of a plain public variable?

  2. Which rule belongs inside the object: discount cannot exceed 100% or the button should be blue?

  3. What bug becomes possible if another part of the program can directly set account.balance = -999999?

Answer Check
  1. So writes can be validated through methods or setters.

  2. The discount validation rule belongs inside the object because it protects business logic.

  3. The object can enter an invalid state and break later calculations.

Exercises

Exercise 1

Build a PayrollAccount class that stores a private salary total and only allows updates through add_payment() when the amount is positive.

Exercise 2

Extend the Product class with a stock property that rejects negative inventory.

Exercise 3

Refactor one earlier class so that callers cannot directly place the object into an invalid state.

Starter Hint

Try converting one raw attribute into a property with a setter. Ask what values should be rejected and why.

Key Takeaway

Encapsulation means an object owns its rules. Other code may request changes, but the object decides whether those changes are valid.

This prepares the next notebook on inheritance and polymorphism: once an object has a clean public interface, subclasses can extend behavior more safely.