Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Properties: Controlled Attributes

โญโญ intermediateโณ 13 min read๐Ÿ“ Lesson 63 of 169

Validate on assignment with @property โ€” keep the simple attribute syntax.

Beginners write obj.age = 300 and hope for the best. Intermediate developers make invalid states impossible โ€” without giving up the simple attribute syntax. That is exactly what @property is for:

class Person:
    def __init__(self, age):
        self.age = age          # goes through the setter below!

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not (0 <= value <= 150):
            raise ValueError(f"age must be 0..150, got {value}")
        self._age = value

Now Person(-5) raises immediately, and so does p.age = -1. The convention: the public name age is a property; the raw value lives in _age (single underscore = internal).

Read-only computed properties

A property with only a getter is read-only โ€” perfect for values derived from real state:

class Rectangle:
    def __init__(self, w, h):
        self.w, self.h = w, h

    @property
    def area(self):
        return self.w * self.h      # no setter: cannot assign

r.area = 99 now raises AttributeError โ€” a good kind of error, because area was never independent state.

Why properties instead of get_x()/set_x()?

Python style is to expose attributes directly and upgrade to properties later if rules appear โ€” callers never change. Java-style getters/setters on every field are noise. Validate at the boundary where bad data enters, and keep the rest plain.

โšก Now practice

Ready to Code
Property DrillsMake invalid states impossible with @property.
2 challenges ยท ยท ~25 min