Python: Encapsulation
Python Encapsulation
1 Overview
📘 Encapsulation in Python
Encapsulation is one of the fundamental principles of object-oriented programming (OOP). It refers to the bundling of data (attributes) and methods that operate on that data within a single unit (class), while restricting direct access to some of the object’s components. This is a means of preventing accidental interference and misuse of the data. Encapsulation helps to hide the internal state of an object and requires all interaction to be performed through an object’s methods, providing better control over the data and reducing system complexity.
In Python, encapsulation is achieved through access modifiers (public, protected, and private) and property decorators that control how attributes are accessed and modified.
2 What is Encapsulation?
Encapsulation is characterized by several key aspects:
- Data Hiding: Internal object details are hidden from the outside world. Only the object itself can directly access its internal state.
- Controlled Access: Access to data is controlled through public methods (getters and setters), allowing validation and logic to be applied when reading or modifying data.
- Abstraction: Users of a class don’t need to know how it works internally; they only need to know what methods are available.
- Modularity: Encapsulated code is more modular and easier to maintain, test, and debug.
- Security: Prevents unauthorized or unintended modifications to sensitive data.
3 Access Modifiers in Python
Unlike languages like Java or C++, Python doesn’t have strict access modifiers. Instead, it uses naming conventions:
- Public, protected and private are not defined in Python.
- In Python, everything is public by default.
- Any attribute or method can be accessed from outside the class.
3.1 Convention
- Public: No underscore prefix. Accessible from anywhere. Normal variable/method name without underscores.
- E.g.,
self.name = 'Cake'
- E.g.,
- Protected: Prefix with a single underscore (
_
). Intended for internal use within the class and its subclasses.- E.g.,
self._discount = 0.1
- E.g.,
- Private: Prefix with double underscores (
__
). Name mangling is applied to make it harder to access from outside.- E.g.,
self.__secret = 'hidden'
- E.g.,
3.2 Public Attributes
- Public attributes can be accessed and modified from anywhere.
- This is the default behavior in Python.
3.3 Protected Attributes
- Protected attributes use a single underscore prefix (
_
). - This is a convention indicating “internal use” - not enforced by Python.
- Can still be accessed, but signals to other developers not to access it directly.
3.4 Private Attributes
- Private attributes use a double underscore prefix (
__
). - Python applies name mangling:
__attribute
becomes_ClassName__attribute
. - Makes it harder (but not impossible) to access from outside the class.
4 Getters and Setters
Getters and setters are methods that provide controlled access to private attributes:
- Getter: Method that returns the value of a private attribute.
- Setter: Method that sets or updates the value of a private attribute with validation.
5 The @property Decorator
Python provides the @property
decorator for a more Pythonic way to implement getters and setters:
- Makes methods accessible like attributes.
- Provides cleaner syntax.
- Allows adding logic to attribute access without changing the interface.
6 Read-Only Properties
You can create read-only properties by defining only a getter without a setter:
7 Practical Example: Temperature Class
A class that stores temperature and provides conversion between Celsius and Fahrenheit:
8 Practical Example: Bank Account
A more complete bank account example with encapsulation:
9 Why Use Encapsulation?
9.1 1. Data Validation
9.2 2. Maintaining Invariants
9.3 3. Flexibility to Change Implementation
10 Encapsulation Best Practices
- Use private attributes for internal state that shouldn’t be modified directly.
- Provide public methods for controlled access to private data.
- Use @property decorator for Pythonic getters and setters.
- Validate data in setters to maintain object integrity.
- Make computed properties read-only when they depend on other attributes.
- Document your interface so users know which methods are public.
- Follow naming conventions: single underscore for protected, double for private.
11 Exercises
11.1 Exercise 1: Person Class
Create a Person
class with encapsulation:
- Private attributes:
__name
,__age
,__email
- Use
@property
decorators for getters - Validate age (must be between 0 and 150)
- Validate email (must contain ‘@’)
11.2 Exercise 2: Car Class
Create a Car
class with:
- Private attributes:
__brand
,__model
,__speed
,__max_speed
- Methods:
accelerate(amount)
,brake(amount)
- Speed cannot be negative or exceed max_speed
- Read-only property for
status
that returns a description
11.3 Exercise 3: Library Book System
Create a Book
class with encapsulation for a library system:
- Private attributes:
__title
,__author
,__isbn
,__is_borrowed
- Methods:
borrow()
,return_book()
- Read-only properties for title, author, isbn
- Property
available
that returns borrowing status
12 Summary
Encapsulation is a fundamental OOP principle that:
- Protects data from unauthorized access and modification
- Provides controlled access through methods and properties
- Enables validation to maintain data integrity
- Improves maintainability by hiding implementation details
- Increases flexibility to change internal implementation without affecting external code
Python uses naming conventions (single and double underscores) and the @property
decorator to implement encapsulation in a Pythonic way.