Managed attributes: property, descriptor, getattr

A setter that refuses negative seats is a property. Descriptors and __getattr__ are the heavier tools. Validate in one place so a form and a CSV importer cannot disagree.

Lab motor

Group fields; pass the whole record.

You will be able to

  • Validate seats (or GST) in one place so a form and a CSV cannot disagree
  • See a setter function as the analog of a property
  • Know descriptors and __getattr__ are heavier laptop tools

A setter that refuses negative seats

The exam cell must not store −4 seats because a CSV had a minus. On a laptop a property (or a descriptor) runs that check whenever anyone assigns. Here you write set_seats(n): if n is negative, Reject; else keep n. A form importer and a kiosk must both call that function.

__getattr__ is the ‘missing name’ hook — useful for lazy fields, easy to hide bugs. Prefer an explicit key policy: missing used is 0, or Reject, written once.

Validate in one place

If the web form checks n >= 0 and the CSV importer does not, the hall chart will lie. Managed attributes are that one place with nicer syntax. Copy the property sample onto a laptop. Do not paste class into this Run box.

Laptop only — property refuses negative seats

class Room:
    def __init__(self):
        self._seats = 10
    @property
    def seats(self):
        return self._seats
    @seats.setter
    def seats(self, n):
        if n < 0:
            raise ValueError("seats")
        self._seats = n

hall = Room()
hall.seats = 40
# hall.seats = -1  # ValueError — same check a CSV importer must share

Words that matter

property
Managed get/set on a laptop — validation in one place.
descriptor
The heavier protocol behind property — rarely your first tool.
__getattr__
Called for a missing attribute — easy to overuse.

Common mistakes

Avoid: Checking seats >= 0 in the form only, not in the CSV importer.

Do this: One set_seats (or a property) every writer calls.

Run it step by step

Each box is a real program. Press Run, change a number, Run again — the output must follow your code.

1. Step 1 — refuse negative seats

The analog of a setter. Nested if, no and/or.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

2. Step 2 — missing field policy

getattr analog: a named default, not a surprise crash.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Example program — Form and CSV share the check

Two writers, one function. INFO when rejected.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Your turn — Reject negative

set_seats(n) returns Reject if n < 0, else n. Print set_seats(-2) so Reject appears.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Self-assessment

Check your understanding before you mark the lesson complete.

1. A property is mainly for…
2. __getattr__ should be…

Progress is stored in a browser cookie on this device.