Getter and Setter in Python
What are Getters and Setters?
- Getter: A method used to retrieve or “get” the value of an instance variable.
- Setter: a method that’s used to set the value of an instance variable, often with some validation logic.
They are widely utilized in Object-Oriented Programming (OOP) to determine access to the private attributes.
What is a Getter?
A getter is a method or function in a class that is used to retrieve the value of a private or protected attribute.
Key Concepts about Getters:
1. Purpose:
- It allows for controlled access to an attribute of the class.
- It makes sure that the value of the attribute is accessible without showing the actual internal implementation.
2. Encapsulation:
- Through a getter, you prevent the direct access to sensitive or private data.
- This follows the encapsulation principle wherein the internal workings of a class are hidden.
3. Read-only Attributes:
- If you only define a getter for an attribute but no setter, then the attribute becomes read-only.
4. Implementation:
- Getters can be implemented either by methods (get_attribute) or using the @property decorator (which makes it look like a regular attribute).
What is a Setter?
A setter is a method or function in a class that is used to update or modify the value of a private or protected attribute. It often includes validation or transformation logic to ensure the attribute is set to a valid value.
Key Points about Setters:
1. Purpose:
- It provides access control to modify the value of an attribute.
- It ensures the integrity of the attribute because the setter function validates before it changes the value.
2. Validation:
- Setters are very useful whenever you want to enforce special conditions about what value is assigned. For instance, its numeric value to be positive or its string to meet some conditions and so on.
3. Encapsulation:
- By using setters, you avoid direct manipulation of the class’s attributes; instead, you control how values are assigned.
4. Implementation:
- Setters can be implemented using methods (set_attribute) or the @.setter decorator, which allows assignment syntax while still enforcing validation logic.
Example 1: Without Getters and Setters
In this case, we define class attributes as public and access them directly. However, there’s no control over the values being assigned.
class Student:
def __init__(self, name, age):
self.name = name # Public attribute
self.age = age # Public attribute
# Usage
s = Student("Alice", 20)
# Output: Access attributes directly
print(s.name) # Output: Alice
print(s.age) # Output: 20
# No validation: Set invalid age
s.age = -5
print(s.age) # Output: -5 (Invalid, but no error is raised!)
Output:
Alice
20
-5
Example 2: Using Regular Methods (Basic Getters and Setters)
Here, we protect the attributes using the single underscore naming convention (e.g., _name) and provide getter and setter methods to access or modify them. This approach adds control and validation.
class Student:
def __init__(self, name, age):
self._name = name # Protected attribute
self._age = age # Protected attribute
# Getter for name
def get_name(self):
return self._name
# Setter for name
def set_name(self, name):
self._name = name
# Getter for age
def get_age(self):
return self._age
# Setter for age with validation
def set_age(self, age):
if age > 0:
self._age = age
else:
raise ValueError("Age must be a positive value!")
# Usage
s = Student("Alice", 20)
# Output: Access using getters
print(s.get_name()) # Output: Alice
print(s.get_age()) # Output: 20
# Update values using setters
s.set_name("Bob")
s.set_age(25)
print(s.get_name()) # Output: Bob
print(s.get_age()) # Output: 25
# Try setting invalid age
try:
s.set_age(-5)
except ValueError as e:
print(e) # Output: Age must be a positive value!
Output:
Alice
20
Bob
25
Age must be a positive value!
Example 3: Using @property Decorators (Pythonic Way)
Python provides the @property decorator for a more concise and readable way to define getters and setters.
class Student:
def __init__(self, name, age):
self._name = name # Protected attribute
self._age = age # Protected attribute
# Getter for name
@property
def name(self):
return self._name
# Setter for name
@name.setter
def name(self, value):
self._name = value
# Getter for age
@property
def age(self):
return self._age
# Setter for age with validation
@age.setter
def age(self, value):
if value > 0:
self._age = value
else:
raise ValueError("Age must be a positive value!")
# Usage
s = Student("Alice", 20)
# Access attributes like variables
print(s.name) # Output: Alice
print(s.age) # Output: 20
# Update attributes
s.name = "Bob"
s.age = 25
print(s.name) # Output: Bob
print(s.age) # Output: 25
# Try setting invalid age
try:
s.age = -10
except ValueError as e:
print(e) # Output: Age must be a positive value!
Output:
Alice
20
Bob
25
Age must be a positive value!
Example 4: Read-Only Properties
You can use @property to create read-only attributes by defining only the getter and omitting the setter.
class Student:
def __init__(self, name, age):
self._name = name # Protected attribute
self._age = age # Protected attribute
# Read-only getter for name
@property
def name(self):
return self._name
# Usage
s = Student("Alice", 20)
# Access read-only property
print(s.name) # Output: Alice
# Attempt to modify read-only property
try:
s.name = "Bob"
except AttributeError as e:
print(e) # Output: can't set attribute
Output:
Alice
can't set attribute
Advantages of Using @property
- Simplifies Code: No need for explicit getter and setter method names like get_name() or set_name().
- Encapsulation: Attributes are still concealed but can be accessed naturally as if they were public.
- Validation: You can easily add logic in the setter to validate or process values.
- Backward Compatibility: Allows transitioning from direct attribute access to using getter/setter logic without breaking existing code.
Comparison Summary
| Feature | Direct Access | Regular Methods | @property Decorators |
|---|---|---|---|
| Ease of Use | Very easy (but unsafe) | Requires explicit calls | Pythonic and concise |
| Encapsulation | None | Achieved | Achieved |
| Validation | Not possible | Possible | Possible |
| Readability | Simple | Verbose | Clean and natural |
| Read-only Properties | Not possible | Possible (with effort) | Easy to define |