What is the python getter setter approach for implementing getters and setters in Python?
Currently, I’m using methods like:
def set_property(property, value):
def get_property(property):
or
object.property = value
value = object.property
What is the most pythonic way to use getters and setters in Python?
Hello @klyni_gg, Hope you are doing great,
Here is the detailed explanation of the above question:-
Using Property Decorators
The most Pythonic way to implement getters and setters in Python is by using the property
decorator. This allows you to define methods for getting, setting, and deleting attributes, while accessing them as if they were regular attributes. This is cleaner and follows Python’s philosophy of ‘beautiful is better than ugly.’
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
"""Getter"""
return self._value
@value.setter
def value(self, value):
"""Setter"""
if value < 0:
raise ValueError("Value must be non-negative")
self._value = value
obj = MyClass(10)
print(obj.value) # Calls the getter
obj.value = 20 # Calls the setter
print(obj.value)
This approach allows for encapsulating logic inside the getter and setter while keeping the syntax simple and intuitive.
Great explanation, @devan-skeem! To add to that, when using the @property
decorator, combining it with @<property_name>.setter
provides modularity and readability. Here’s another variation using the same decorators:
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value):
if value < 0:
raise ValueError("Value must be non-negative")
self._value = value
obj = MyClass(10)
print(obj.value) # Getter
obj.value = 15 # Setter
print(obj.value)
This ensures controlled access to the attribute while keeping the code structure clear. It’s especially helpful when you want to enforce additional logic within setters or getters.
Excellent points, @devan-skeem and @Rashmihasija! Another interesting approach to control attribute access, especially in advanced scenarios, is using __getattr__
and __setattr__
. This method is more dynamic and offers greater flexibility, although it should be used carefully to avoid complicating the code.
class MyClass:
def __init__(self, value):
self._value = value
def __getattr__(self, name):
if name == "value":
return self._value
raise AttributeError(f"{name} not found")
def __setattr__(self, name, value):
if name == "value":
if value < 0:
raise ValueError("Value must be non-negative")
self._value = value
else:
super().__setattr__(name, value)
obj = MyClass(10)
print(obj.value) # Calls __getattr__
obj.value = 20 # Calls __setattr__
print(obj.value)
This technique is powerful for scenarios requiring dynamic attribute handling. However, for simpler use cases, the property
decorator is generally preferable for its clarity and maintainability.