0%

Gültigen Objektzustand schützen · Übung

Änderungen mit Property-Settern steuern

Bisher ging alles in eine Richtung: weniger Möglichkeiten, ein Objekt von außen zu beschreiben. Lektion 2 lehnte eine ungültige Erzeugung ab, Lektion 3 ersetzte Zuweisungen durch Ereignisse, und Lektion 5 machte den Punktestand lesbar, aber nicht beschreibbar.

Manchmal soll ein Wert tatsächlich änderbar sein. Die Dauer eines Timers könnte nach einer Durchsicht angepasst werden. Jemand hat sich schlicht anders entschieden.

Eine Property, die einen Wert annimmt

Eine Property kann einen zweiten Teil definieren, der bei einer Zuweisung ausgeführt wird:

Try it

Der lesende Teil ist @property. Der schreibende Teil ist @minutes.setter, benannt nach der zugehörigen Property. Beide Methoden heißen minutes: Eine wird beim Lesen ausgeführt, die andere beim Zuweisen. Beachte, dass auch __init__ die Zuweisung self.minutes = minutes verwendet. Die Erzeugung kann die Regel somit nicht umgehen.

Eine ungültige Zuweisung wird nun abgelehnt:

timer.minutes = 0

Die Klasse prüft den Wert, bevor sie ihn speichert. Löst die Prüfung eine Ausnahme aus, findet die Zuweisung nicht statt, und der alte gültige Wert bleibt erhalten.

Was tut Python, wenn ein Programm timer.minutes = 5 ausführt?

Einen Setter bewusst einsetzen

Jedes Attribut in eine Property zu verpacken fügt Code hinzu, ohne Sicherheit zu gewinnen. Verwende einen Setter, wenn beide Bedingungen gelten:

  • Aufrufender Code muss diesem einzelnen Attribut tatsächlich einen Wert zuweisen können.

  • Für das Attribut gibt es eine Regel, deren Durchsetzung sinnvoll ist.

Ein aus erfassten Antworten berechneter Punktestand erfüllt die erste Bedingung nicht und bleibt daher schreibgeschützt. Die anpassbare Punktzahl einer Frage in der Übung erfüllt beide.

Die Übung ergänzt einen begründeten Setter und prüft den entscheidenden Fehlerfall: Eine abgelehnte Zuweisung lässt den bisherigen Wert unangetastet. Die nächste Lektion behandelt ein anderes Problem: eine tatsächliche Änderung, die mehrere Attribute gemeinsam aktualisieren muss.

Aufgabe

Gib points einen Setter, der jeden Wert kleiner oder gleich null ablehnt und ValueError auslöst. Das Lesen von question.points soll wie zuvor funktionieren. Leite den Anfangswert aus dem Konstruktor durch denselben Setter, damit ungültige Fragen die Regel bei der Erzeugung nicht umgehen können.

Führe das Programm aus. Die abgelehnte Zuweisung soll ihre Meldung ausgeben und die bisherige Punktzahl der Frage exakt erhalten.