Demystifying Encapsulation and Information Hiding in Python
Defining the Two Pillars of Design
Many developers use Customer class that contains names, IDs, and addresses. It creates a complete representation of an entity. Beyond grouping, it also establishes boundaries. These boundaries restrict how external code interacts with internal data, often using access modifiers like private or protected members.
Information hiding is the strategic concealment of implementation details. It provides a "black box" interface, allowing other modules to interact with a component without knowing its internal mechanics. When you use a
Implementation and Access Control
In
class Order:
def __init__(self):
# Protected member: a boundary for encapsulation
self._payment_status = "PENDING"
def pay(self):
# Information hiding: user doesn't see the internal logic
self._payment_status = "PAID"
def is_paid(self) -> bool:
return self._payment_status == "PAID"
In this Order class, _payment_status is protected. By providing methods like is_paid(), we hide the internal representation. If we later change the status from a string to an integer, external code remains untouched because it relies on the method, not the variable.
Impact on Cohesion and Coupling
These concepts directly influence the health of your codebase. Encapsulation increases cohesion by ensuring that a class does exactly what it's supposed to do and nothing more. Information hiding reduces coupling by removing dependencies between different parts of the system. High cohesion and low coupling make your software easier to maintain, test, and scale over time.
Syntax Notes and Best Practices
Python uses the _ prefix for protected members and __ for private members (which triggers name mangling). Always prefer high-level methods over direct variable access to maintain the integrity of your information hiding strategy. Use

Fancy watching it?
Watch the full video and context