1. Introduction: Connecting Encapsulation to Access Methods
In the study of data encapsulation, an object's internal data is hidden from the outside world by declaring variables as private using double underscores (__). Because the outside program cannot directly read or modify private variables, the class provides dedicated public methods through which external code can safely interact with that private data.
In object-oriented programming, these specialized access methods are known as Getters and Setters:
- Getters: Functions designed to retrieve (get) the value of a class's internal data attributes.
- Setters: Functions designed to assign or update (set) the value of a class's internal data attributes.
Whenever a private data member is declared in a class, best practice is to pair it with corresponding getter and setter methods to control external access.
2. Why Setters Are Essential: Sanity Checks & Data Validation
The true value of a setter method becomes clear when inspecting its body. If users could modify attributes directly, invalid or illogical data could enter the system.
A setter introduces validation logic (sanity checks) before assigning values to private members:
- Logical boundaries: A student's grade must fall between 0 and 100. Even if a student claims to have given 110% effort, the maximum allowable grade remains 100.
- Preventing negative values: If a user enters a negative grade (such as -20 or -95), whether accidentally or intentionally, the setter rejects it because a negative grade is invalid.
- Protecting class ownership and quality: One of OOP's primary goals is code reusability. When you publish a class for other developers to instantiate and use in their applications, your class represents your work. If your class allowed an object to store -5 as a grade, the class design itself would appear flawed. Setters protect the class from accepting illogical values.
3. Implementation Walkthrough in Jupyter Notebook: The Student Class
The following implementation defines a Student class with a private __grade attribute, a getter (get_grade), and a setter with validation (set_grade):
class Student:
# 1. Constructor initializing name and private grade
def __init__(self, name, grade):
self.name = name
self.__grade = grade # Private data member prefixed with '__'
# 2. Getter method to retrieve the private grade
def get_grade(self):
return self.__grade
# 3. Setter method with validation (sanity check)
def set_grade(self, new_grade):
if 0 <= new_grade <= 100:
self.__grade = new_grade
else:
print(f"Invalid grade: {new_grade}. Grade must be between 0 and 100.")
4. Testing Valid Updates and Retrievals
When an object is instantiated and updated with valid data:
# 1. Initializing student1 with name "Ali" and initial grade 90
student1 = Student("Ali", 90)
# 2. Modifying grade to 95 using the setter method
student1.set_grade(95)
# 3. Retrieving and printing the updated grade via the getter
print("Updated Grade:", student1.get_grade())
Execution Walkthrough
- The constructor initializes
student1 with a grade of 90.
- Calling
student1.set_grade(95) passes 95 to the setter. Because 95 is between 0 and 100, the validation check passes, and self.__grade updates to 95.
- Calling
student1.get_grade() returns the updated value.
Output:
Updated Grade: 95
5. Testing Invalid Inputs and Data Protection
If an external user attempts to pass an invalid value, such as a negative grade:
# Attempting to assign an invalid grade of -95
student1.set_grade(-95)
# Checking the grade value using the getter
print("Current Stored Grade:", student1.get_grade())
Execution Walkthrough
- When
set_grade(-95) runs, the sanity check identifies -95 as outside the 0 to 100 range.
- The setter displays an error notification and refuses to update the private attribute.
- Calling
student1.get_grade() confirms that the private variable retained its previously valid value (95) rather than being corrupted by the invalid input.
Output:
Invalid grade: -95. Grade must be between 0 and 100.
Current Stored Grade: 95
6. Formatting Output Inside Getters
Getters are not limited to returning raw stored values. A getter can also transform internal data into user-friendly formats before returning it—for example, converting numerical marks into letter grades such as A, B, C, or D.