Understanding Python Property Management Techniques

Python provides two primary approaches for implementing managed attributes: the @property decorator and the property() function. Both methods enable controlled access to instance attributes while maintaining clean syntax.

Using the @property Decorator

The @property decorator transforms methods into managed attributes, allowing you to define getter, setter, and deleter methods while using attribute-style access. This approach provides a clean way to implement validation and processing logic.

class TemperatureControl:
    def __init__(self):
        self._internal_temp = 20.0

    @property
    def temperature(self):
        """Current temperature in Celsius"""
        return self._internal_temp

    @temperature.setter
    def temperature(self, new_temp):
        if not isinstance(new_temp, (int, float)):
            raise TypeError("Temperature must be numeric")
        if new_temp < -273.15:
            raise ValueError("Temperature below absolute zero")
        self._internal_temp = new_temp

    @temperature.deleter
    def temperature(self):
        self._internal_temp = None

thermostat = TemperatureControl()
print(thermostat.temperature)
thermostat.temperature = 25.5
print(thermostat.temperature)
del thermostat.temperature
print(thermostat.temperature)
20.0
25.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 13, in temperature
AttributeError: 'TemperatureControl' object has no attribute '_internal_temp'

Using the property() Function

The property() function offers an alternative way to create managed attributes by binding getter, setter, and deleter methods to a single attribute.

Syntax

property(fget=None, fset=None, fdel=None, doc=None)

Parameters

  • fget: Function to retrieve attribute value
  • fset: Function to set attribute value
  • fdel: Function to delete attribute
  • doc: Documentation string for the property
class BankAccount:
    def __init__(self, initial_balance=0):
        self._balance = initial_balance

    def get_balance(self):
        return self._balance

    def set_balance(self, amount):
        if amount < 0:
            raise ValueError("Balance cannot be negative")
        self._balance = amount

    def del_balance(self):
        self._balance = 0

    balance = property(
        get_balance, 
        set_balance, 
        del_balance, 
        "Account balance in dollars"
    )

account = BankAccount(1000)
print(account.balance)
account.balance = 1500
print(account.balance)
del account.balance
print(account.balance)
1000
1500
0

When an account instance accesses balance, Python automatically calls get_balance(). Setting account.balance triggers set_balance(), and del account.balance invokes del_balance(). This encapsulation allows you to maintain invariants and add validation logic while preserving attribute access syntax.

Tags: python properties decorators OOP attributes

Posted on Thu, 07 May 2026 14:05:54 +0000 by nmreddy