Sharpen your Python OOP skills by identifying and correcting common encapsulation mistakes. This hands-on debugging exercise covers beginner to advanced scenarios, helping you master access modifiers, properties, and data protection in real-world code.
Identify and fix the encapsulation mistake in the following code:
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
print("Insufficient funds")
self.balance -= amount
Hint: 💡 Direct access to attributes violates encapsulation principles.
Issue: The balance attribute is directly accessible and modifiable from outside the class.
class BankAccount:
def __init__(self, balance):
self._balance = balance
def withdraw(self, amount):
if amount > self._balance:
print("Insufficient funds")
return
self._balance -= amount
def get_balance(self):
return self._balance
Fix the encapsulation issue in this temperature class:
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
Hint: 💡 Temperature values should have validation to prevent impossible values.
Issue: Direct attribute access allows setting invalid temperatures.
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
Find and fix the encapsulation problems in this student class:
class Student:
def __init__(self, name, grades):
self.name = name
self.grades = grades
Hint: 💡 Both attributes need protection and grades should have controlled modification.
Issue: Direct access to both name and grades violates encapsulation.
class Student:
def __init__(self, name, grades):
self._name = name
self._grades = list(grades)
@property
def name(self):
return self._name
def add_grade(self, grade):
self._grades.append(grade)
def get_grades(self):
return tuple(self._grades)
Identify and fix the property implementation mistake:
class Circle:
def __init__(self, radius):
self.__radius = radius
@property
def radius(self):
return self.__radius
@radius.setter
def radius(self, value):
self.radius = value
Hint: 💡 The setter is causing infinite recursion.
Issue: Using self.radius instead of self.__radius in the setter.
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:
raise ValueError("Radius must be positive")
self.__radius = value
Fix the multiple encapsulation issues in this shopping cart implementation:
class ShoppingCart:
def __init__(self):
self.items = []
self.total = 0
def add_item(self, item, price):
self.items.append((item, price))
self.total += price
Hint: 💡 Both the items list and total should be protected from direct modification.
Issue: External code can directly modify items and total, breaking consistency.
class ShoppingCart:
def __init__(self):
self._items = []
self._total = 0
def add_item(self, item, price):
self._items.append((item, price))
self._total += price
def get_items(self):
return tuple(self._items)
def get_total(self):
return self._total
def remove_item(self, index):
if 0 <= index < len(self._items):
item, price = self._items.pop(index)
self._total -= price