Ein Programm über mehrere Dateien organisieren · Übung
Module und Namensräume
Für die Module dieses Kapitels ist ein Modul eine Python-Datei mit zusammengehörigen Definitionen. Python bietet auch andere Modulformen. Eine gewöhnliche .py-Datei reicht für dieses Projekt aus.
Ein Modul ist nützlich, weil seine Namen zu ihm gehören. Zwei Dateien können beide Question definieren, ohne zusammenzustoßen. Verwendender Code muss sagen, welches er meint.
Eine eigene Datei importieren
Kapitel 8 hat ein Werkzeug aus der Standardbibliothek geliehen:
from dataclasses import dataclass
Dieselbe Anweisung erreicht eine eigene Datei. Enthält dein Projekt models.py, ist models ein importierbares Modul:
import models
question = models.Question("Which keyword starts a function?", "def", 2)
Wenn dieses Projekt von main.py aus startet, findet Python models.py im Projektverzeichnis, führt es einmal aus und liefert ein Objekt mit allem, was die Datei definiert hat. models.Question liest aus diesem Objekt.
Beachte, was fehlt: kein Pfad, kein .py und keine Anführungszeichen. Du importierst den Namen des Moduls. Das ist der Dateiname ohne Endung.
Namensräume konkret
Stell dir nun eine zweite Datei survey.py vor, die für ihre Zwecke ebenfalls Question definiert. In einer Datei würden beide um den Namen kämpfen. Als Module tun sie das nicht:
import models
import survey
quiz_question = models.Question("Which keyword starts a function?", "def", 2)
survey_question = survey.Question("How difficult was this?")
models.Question und survey.Question sind verschiedene Klassen. Der Code sagt jedes Mal, welche er meint. Genau das ist ein Namensraum: ein Ort für Namen, damit derselbe Name an zwei Orten zwei verschiedene Dinge bleibt.
Das ist dieselbe Idee wie bei self.answer, das ein Attribut eines Objekts statt einer freien Variablen bezeichnet, nur eine Ebene höher.
Dein Projekt enthält models.py. Welche Zeile importiert das Modul unter dem Namen models, sodass du models.Question(...) schreiben kannst?
Aufteilen heißt verschieben, nicht neu schreiben
Der kommende Schritt ist die einfachste Form von Refactoring: Text verlässt eine Datei und kommt unverändert in einer anderen an.
Bewusst vorzugehen lohnt sich trotzdem. Die interessante Frage ist nicht, wie du eine Klasse verschiebst, sondern welche Klassen zusammengehören. Question, Quiz und Attempt gehören in dasselbe Modul, weil sie dieselbe Art von Dingen sind: der Wortschatz des Programms und die zugehörigen Regeln. Diese Gruppe heißt Domäne. Lektion 6 stellt ihr einen weiteren Bereich zur Seite.
Zurück bleibt alles, was nicht zu diesem Wortschatz gehört: einen Versuch in Textzeilen umzuwandeln, ein bestimmtes Quiz zusammenzustellen und das Programm auszuführen. Das sind Aufgaben, die mit der Domäne erledigt werden, keine Teile davon.
Die Übung
Kopiere Question, Quiz und Attempt aus main.py exakt so, wie sie sind, in die vorgegebene Datei models.py.
Diese Lektion öffnet models.py. Wähle in der Dateiansicht main.py, um die ursprünglichen Klassen zu lesen. Kehre dann zum Kopieren zu models.py zurück.
Lass main.py in diesem Schritt unverändert, damit Run noch das funktionierende Original ausführt. Die nächste Lektion schließt den Umzug ab, indem sie die doppelten Klassen löscht und das neue Modul importiert. Submit prüft hier nur models.py.
Aufgabe
Kopiere Question, Quiz und Attempt in die vorgegebene Datei models.py.
Kopiere alle drei Klassen exakt so, wie sie in main.py stehen. Dies ist ein Umzug, keine Neufassung: Kein Verhalten soll sich ändern, und nichts muss umbenannt werden.
Die drei bilden den Wortschatz des Programms und gehören deshalb zusammen. models.py soll nur sie enthalten. Lass report_lines, build_quiz und main an ihrem bisherigen Platz.
Lass die ursprünglichen Klassen vorerst in main.py. Run verwendet weiterhin das ursprüngliche Programm; Submit prüft models.py. Die nächste Lektion löscht die Duplikate und importiert sie stattdessen. Damit ist der Umzug abgeschlossen.