Properties and Getters/Setters

Loading

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:

  1. Using instance methods (get_, set_)
  2. Using the property() function
  3. Using the @property decorator (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 calling property().

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

ApproachGetter/Setter Methodsproperty() Function@property Decorator
DefinitionUses explicit get_ and set_ methodsUses property(get, set)Uses @property and @<name>.setter
Usagep.get_age(), p.set_age(30)p.age, p.age = 30p.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., area property in Rectangle).
  • 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.

Leave a Reply

Your email address will not be published. Required fields are marked *