The importance of encapsulation lies in several key aspects:
Python provides several mechanisms to implement encapsulation. Let’s explore these with examples:
In Python, we can create private attributes by prefixing the attribute name with double underscores (__
). This triggers name mangling, which makes the attribute harder to access from outside the class.
class BankAccount:
def __init__(self, account_number, balance):
self.__account_number = account_number # Private attribute
self.__balance = balance # Private attribute
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return True
return False
def get_balance(self):
return self.__balance
# Usage
account = BankAccount("1234567890", 1000)
print(account.get_balance()) # Output: 1000
account.deposit(500)
print(account.get_balance()) # Output: 1500
account.withdraw(200)
print(account.get_balance()) # Output: 1300
# This will raise an AttributeError
# print(account.__balance)
In this example:
__account_number
and __balance
are private attributes.deposit
, withdraw
, get_balance
) to interact with these private attributes.__balance
from outside the class will raise an AttributeError
exception.Python’s @property
decorator allows us to define methods that can be accessed like attributes, providing a more Pythonic way of implementing getters and setters.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value > 0:
self._radius = value
else:
raise ValueError("Radius must be positive")
@property
def area(self):
return 3.14159 * self._radius ** 2
# Usage
circle = Circle(5)
print(circle.radius) # Output: 5
print(circle.area) # Output: 78.53975
circle.radius = 7
print(circle.radius) # Output: 7
print(circle.area) # Output: 153.93791
# This will raise a ValueError
# circle.radius = -1
In this example:
_radius
is a protected attribute (single underscore is a convention for protected attributes in Python).radius
property provides get and set access to _radius
with validation.area
property is read-only and calculated on-the-fly.The benefits of encapsulation are numerous:
Best practices for encapsulation in Python include:
Let’s look at a more complex example that demonstrates these practices:
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
self.__projects = []
@property
def name(self):
return self.__name
@property
def salary(self):
return self.__salary
@salary.setter
def salary(self, value):
if value > 0:
self.__salary = value
else:
raise ValueError("Salary must be positive")
def add_project(self, project):
"""
Add a project to the employee's project list.
:param project: string representing the project name
"""
self.__projects.append(project)
def remove_project(self, project):
"""
Remove a project from the employee's project list.
:param project: string representing the project name
:return: True if project was removed, False if not found
"""
if project in self.__projects:
self.__projects.remove(project)
return True
return False
@property
def project_count(self):
return len(self.__projects)
def __str__(self):
return f"Employee: {self.__name}, Salary: ${self.__salary}, Projects: {self.project_count}"
# Usage
emp = Employee("John Doe", 50000)
print(emp.name) # Output: John Doe
print(emp.salary) # Output: 50000
emp.add_project("Project A")
emp.add_project("Project B")
print(emp.project_count) # Output: 2
emp.salary = 55000
print(emp) # Output: Employee: John Doe, Salary: $55000, Projects: 2
emp.remove_project("Project A")
print(emp.project_count) # Output: 1
# This will raise an AttributeError
# print(emp.__projects)
This example demonstrates:
__name
, __salary
, __projects
)name
, salary
, project_count
)add_project
, remove_project
)__str__
method for a nice string representation of the objectBy following these practices, we create a class that is both flexible and robust, embodying the principle of encapsulation.
Cheers for making it this far! I hope this journey through the programming universe has been as fascinating for you as it was for me to write down.
We’re keen to hear your thoughts, so don’t be shy – drop your comments, suggestions, and those bright ideas you’re bound to have.
Also, to delve deeper than these lines, take a stroll through the practical examples we’ve cooked up for you. You’ll find all the code and projects in our GitHub repository learn-software-engineering/examples.
Thanks for being part of this learning community. Keep coding and exploring new territories in this captivating world of software!
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.