Getters and Setters in Python
Getters and setters are methods used to access and modify the attributes of a class in a controlled manner. They provide encapsulation, allowing you to protect your data by controlling how it is accessed or modified. In Python, you can create getters and setters using traditional methods or the @property
decorator. This article explains these concepts with examples.
Why Use Getters and Setters?
Directly accessing attributes of a class is possible in Python, but it is not always ideal. Getters and setters allow you to:
- Validate data before setting it.
- Protect sensitive attributes from being directly modified.
- Add additional logic when getting or setting an attribute.
Traditional Getters and Setters
Example 1: Using Methods for Getters and Setters
class Person: def __init__(self, name, age): self.__name = name # Private attribute self.__age = age # Private attribute def get_name(self): return self.__name def set_name(self, name): if name: self.__name = name else: print("Invalid name") def get_age(self): return self.__age def set_age(self, age): if age > 0: self.__age = age else: print("Invalid age") person = Person("Alice", 30) print(person.get_name()) person.set_name("Alicia") print(person.get_name()) print(person.get_age()) person.set_age(35) print(person.get_age())
In this example, get_name
and set_name
are used to access and modify the __name
attribute, while get_age
and set_age
do the same for __age
.
Using @property Decorator
Python provides a more elegant way to create getters and setters using the @property
decorator. This approach allows you to define methods that act like attributes.
Example 2: Using @property
class Rectangle: def __init__(self, width, height): self.__width = width self.__height = height @property def width(self): return self.__width @width.setter def width(self, value): if value > 0: self.__width = value else: print("Width must be positive") @property def height(self): return self.__height @height.setter def height(self, value): if value > 0: self.__height = value else: print("Height must be positive") rectangle = Rectangle(4, 5) print(rectangle.width) rectangle.width = 10 print(rectangle.width) rectangle.height = -2 # Invalid value
In this example, the width
and height
properties use the @property
and @property_name.setter
decorators to define getters and setters.
Benefits of @property
Using @property
makes the code more readable and intuitive. It allows you to use getter and setter methods like attributes without parentheses.
Getter-Only Properties
Sometimes, you may want an attribute to be read-only. You can achieve this by defining only the getter method without a setter.
Example 3: Read-Only Attribute
class Circle: def __init__(self, radius): self.__radius = radius @property def radius(self): return self.__radius circle = Circle(5) print(circle.radius) # circle.radius = 10 # Raises AttributeError
In this example, the radius
attribute is read-only because no setter method is defined.
Combining Getters and Setters
Getters and setters are often combined to manage attributes with additional logic for validation or computation.
Example 4: Combining Getter and Setter
class Employee: def __init__(self, name, salary): self.__name = name self.__salary = salary @property def salary(self): return self.__salary @salary.setter def salary(self, value): if value > 0: self.__salary = value else: print("Salary must be positive") employee = Employee("John", 5000) print(employee.salary) employee.salary = 6000 print(employee.salary) employee.salary = -1000 # Invalid value
Here, the salary
property manages access and modification of the private attribute __salary
.
Key Points
- Getters and setters provide controlled access to class attributes.
- Use traditional methods for explicit getter and setter methods.
- Use the
@property
decorator for a more Pythonic approach. - Define only getter methods for read-only attributes.
Conclusion
Getters and setters are essential for encapsulation in object-oriented programming. Whether using traditional methods or the @property
decorator, they ensure data validation, protect sensitive attributes, and provide a cleaner interface for accessing and modifying class attributes.