Protecting Valid Object State · practice
Control Changes with Property Setters
Everything so far has pushed in one direction: fewer ways for the outside world to write to an
Sometimes a
A property that accepts a value
A property can define a second half that runs when someone assigns to it:
The reading half is @property. The writing half is @minutes.setter, named after the property it belongs to. Both minutes: one runs during reading and the other during assignment. Notice that __init__ uses self.minutes = minutes, too, so construction cannot bypass the rule.
Now an invalid assignment is refused:
timer.minutes = 0
The class inspects the value before storing it. If the check raises, the assignment never happens and the old valid value remains.
What does Python do when a program runs timer.minutes = 5?
Use a setter deliberately
Wrapping every attribute in a property adds code without adding safety. Reach for a setter when both
callers genuinely need to assign this one attribute;
the attribute has a rule worth enforcing.
A score computed from recorded answers fails the first condition, so it stays read-only. In the exercise, a question’s adjustable point value meets both.
The exercise adds one justified setter and checks the load-bearing failure case: a refused assignment leaves the previous value untouched. The next lesson handles a different problem: one real change that must update several attributes together.
Task
Give points a setter that refuses any question.points should keep working as before. Route the constructor’s initial value through the same setter so invalid questions cannot bypass the rule during construction.
Run the program. The refused