![]()
In Python, getters and setters are used to control access to class attributes, ensuring encapsulation and data validation. Instead of accessing attributes directly, we use property methods to manage them safely.
Python provides three ways to define getters and setters:
- Using instance methods (
get_,set_) - Using the
property()function - Using the
@propertydecorator (recommended approach)
1. Using Instance Methods (Basic Approach)
Example: Defining Getters and Setters Manually
class Person:
def __init__(self, name, age):
self._name = name # Convention: _name (indicates "protected" variable)
self._age = age
def get_age(self): # Getter
return self._age
def set_age(self, new_age): # Setter
if new_age > 0:
self._age = new_age
else:
print("Age must be positive!")
p = Person("Alice", 25)
# Using getter and setter methods
print(p.get_age()) # Output: 25
p.set_age(30)
print(p.get_age()) # Output: 30
p.set_age(-5) # Invalid case
Why use this?
- Allows validation before updating attributes.
- Follows traditional object-oriented programming (OOP) conventions.
Downside: Requires explicit method calls (get_age(),set_age()).
2. Using the property() Function
Python’s built-in property() function allows creating properties dynamically.
Example: property() Function for Getters and Setters
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if new_age > 0:
self._age = new_age
else:
print("Age must be positive!")
age = property(get_age, set_age) # Creating property
p = Person("Bob", 40)
print(p.age) # Calls get_age() → Output: 40
p.age = 45 # Calls set_age()
print(p.age) # Output: 45
p.age = -5 # Invalid case
Why use property()?
- Allows attribute-like access instead of
get_age(). - Still supports validation via setter methods.
Downside: Still requires explicitly callingproperty().
3. Using the @property Decorator (Recommended)
The @property decorator makes getter and setter methods more Pythonic and readable.
Example: Using @property Decorators
class Person:
def __init__(self, name, age):
self._name = name
self._age = age # Private attribute
@property
def age(self): # Getter
return self._age
@age.setter
def age(self, new_age): # Setter
if new_age > 0:
self._age = new_age
else:
print("Age must be positive!")
p = Person("Charlie", 35)
print(p.age) # Calls @property (getter) → Output: 35
p.age = 40 # Calls @age.setter
print(p.age) # Output: 40
p.age = -5 # Invalid case
Why use @property?
✅ More Pythonic and readable
✅ Encapsulation with automatic attribute access
✅ No need for explicit method calls (get_age(), set_age())
4. Read-Only Properties (No Setter)
If we don’t want an attribute to be modified after object creation, we can omit the @property setter.
Example: Creating Read-Only Property
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius # Read-only
c = Circle(10)
print(c.radius) # Output: 10
c.radius = 15 # Error! Read-only property
Why use this?
- Prevents accidental modifications.
- Useful for constants or calculated values.
5. Deleting a Property (@property.deleter)
You can also define deleters to delete an attribute when needed.
Example: Using @property.deleter
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def age(self):
return self._age
@age.deleter
def age(self):
print("Deleting age...")
del self._age
p = Person("Diana", 28)
del p.age # Calls deleter
Why use this?
- Useful for cleanup operations.
6. Calculated Properties (Derived Attributes)
We can use @property to create dynamic properties that depend on other attributes.
Example: Calculated Properties
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self): # No setter (read-only)
return self.width * self.height
r = Rectangle(5, 10)
print(r.area) # Output: 50
r.width = 6
print(r.area) # Output: 60 (Updated)
Why use this?
- Allows automatic updates when dependent attributes change.
7. Summary: Different Ways to Implement Properties
| Approach | Getter/Setter Methods | property() Function | @property Decorator |
|---|---|---|---|
| Definition | Uses explicit get_ and set_ methods | Uses property(get, set) | Uses @property and @<name>.setter |
| Usage | p.get_age(), p.set_age(30) | p.age, p.age = 30 | p.age, p.age = 30 |
| Readability | Less readable | Better readability | Most Pythonic |
| Encapsulation | Yes | Yes | Yes |
| Preferred? | No | Sometimes | Recommended |
8. When to Use Properties in Python?
Use @property when:
- You want to control attribute access.
- You need data validation before modifying an attribute.
- You want calculated properties (e.g.,
areaproperty inRectangle). - You want to make an attribute read-only (omit setter).
Avoid @property if:
- The attribute does not require validation or special handling.
- You have complex logic, where a method might be better.
