Add property getter setter validation in Python

Shows how to use @property with a setter to validate values before assigning them in a Python class.

Easy Python 3.9+ Aug 9, 2026 OOP & classes 16 views 0 copies

Python code

37 lines
Python 3.9+
class Temperature:
    def __init__(self, celsius=0):
        self._celsius = celsius  # Use underscore to avoid recursion
    
    @property
    def celsius(self):
        """Getter returns the stored value."""
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """Setter validates before storing."""
        if not isinstance(value, (int, float)):
            raise TypeError("Temperature must be a number")
        if value < -273.15:
            raise ValueError("Temperature cannot be below absolute zero")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        """Derived property with getter only."""
        return self._celsius * 9/5 + 32

if __name__ == "__main__":
    temp = Temperature()
    temp.celsius = 25
    print(f"Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenheit}")
    
    try:
        temp.celsius = -300
    except ValueError as e:
        print(f"Validation error: {e}")
    
    try:
        temp.celsius = "hot"
    except TypeError as e:
        print(f"Type error: {e}")

Output

stdout
Celsius: 25, Fahrenheit: 77.0
Validation error: Temperature cannot be below absolute zero
Type error: Temperature must be a number

How it works

The @property decorator turns a method into a read-only attribute. The setter allows custom validation on assignment, raising TypeError for wrong types and ValueError for out-of-range values. Using an underscore prefix (_celsius) for the internal attribute prevents recursion because the setter is bypassed during __init__. The fahrenheit property is derived and has no setter, so it's read-only.

Common mistakes

  • Forgetting to use an underscore for the internal attribute, causing infinite recursion.
  • Not validating types or ranges, allowing invalid data to be stored.
  • Trying to set a read-only property (like fahrenheit) without defining a setter.

Variations

  1. Use `@celsius.deleter` to handle deletion of the property.
  2. Use `dataclasses` with custom `__post_init__` validation instead.

Real-world use cases

  • Validating user input in a settings object before it's applied.
  • Ensuring sensor readings stored in a data model stay within physical limits.
  • Enforcing business rules on financial fields like non-negative balances.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.