Challenge your understanding of Python's Object-Oriented Programming with these multiple-choice questions on encapsulation. Ideal for beginners, students, and job seekers to reinforce key OOP concepts.
A way to hide internal implementation details and expose only necessary features
Encapsulation helps in restricting access to certain components and prevents unintended modifications.
By prefixing the attribute name with double underscores `__`
In Python, double underscores `__` make an attribute name-mangled, restricting direct access.
To control access and modification of private attributes
Getters and setters allow controlled access to private attributes, enabling validation or modification checks.
class BankAccount:
def __init__(self):
self.__balance = 100
def get_balance(self):
return self.__balance
acc = BankAccount()
print(acc.__balance)
Error: AttributeError (private attribute access)
Double underscores make `__balance` private, so direct access outside the class raises an error.
By using a getter method
The safest way is to use a getter method (e.g., `get_balance()`) instead of direct access.
It indicates that the variable is for internal use (convention).
A single underscore is a naming convention to suggest that a variable is for internal use (not enforced by Python). It should be accessed only within the class or its subclasses.
class Student:
def __init__(self):
self.__name = "Alice"
s = Student()
print(s.__name)
Error: AttributeError (private attribute access)
Private attributes (prefixed with `__`) cannot be accessed directly outside the class.
class Student:
def __init__(self):
self.__name = "Alice"
def get_name(self):
return self.__name
s = Student()
print(s.get_name())
Alice
The `get_name()` method provides controlled access to the private `__name` attribute.
class Temperature:
def __init__(self):
self.__celsius = 30
def get_fahrenheit(self):
return (self.__celsius * 9/5) + 32
t = Temperature()
print(t.get_fahrenheit())
86
The private `__celsius` is used internally to compute Fahrenheit (30°C = 86°F).
It renames the attribute to `_ClassName__attribute`
Name mangling changes the attribute name to `_ClassName__attribute` to avoid accidental access.
`@property`
The `@property` decorator allows defining a method as a read-only attribute.
class Account:
def __init__(self):
self.__balance = 0
def deposit(self, amount):
self.__balance += amount
def withdraw(self, amount):
if amount <= self.__balance:
self.__balance -= amount
else:
print("Insufficient funds!")
def get_balance(self):
return self.__balance
acc = Account()
acc.deposit(100)
acc.withdraw(30)
print(acc.get_balance())
70
The private `__balance` is modified only via methods (`deposit()` and `withdraw()`).
class Person:
def __init__(self):
self.__age = 25
@property
def age(self):
return self.__age
@age.setter
def age(self, value):
if value > 0:
self.__age = value
else:
print("Invalid age!")
p = Person()
p.age = -5
print(p.age)
25
The setter rejects negative values, so `__age` remains unchanged (25).
class Car:
def __init__(self):
self.__speed = 0
def accelerate(self):
self.__speed += 10
def brake(self):
self.__speed = max(0, self.__speed - 10)
def get_speed(self):
return self.__speed
c = Car()
c.accelerate() # Typo in method name
print(c.get_speed())
Error: Method not found
The typo `accelerate()` → `accelerate()` causes an `AttributeError`.
class Secret:
def __init__(self):
self.__key = "1234"
def _get_key(self):
return self.__key[::-1] # Reversed
s = Secret()
print(s._get_key())
4321
Single underscore `_get_key()` is