LU09.L01a - Schulverwaltung mit Types
In Python sind Typangaben bei der Definition von Variablen, Funktionen oder Methoden optional. Python ist eine dynamisch typisierte Sprache, das heisst, der Datentyp einer Variable wird zur Laufzeit automatisch ermittelt.
Du kannst die Datentypen angeben, um die Lesbarkeit zu verbessern und Fehler frühzeitig zu erkennen, aber der Interpreter erzwingt sie nicht. Im Zusammenhang mit zweiseitigen Beziehungen führt die Verwendung von Datentypen aber zu einem zirkulären Import (SchoolClass importiert Student, Student importiert SchoolClass, welches Student importiert, …).
Dieses Codebeispiel zeigt eine Lösung, um die zirkulären Imports zu verhindern.
- school_class.py
""" Provides the class SchoolClass """ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from student import Student class SchoolClass: """ A schoolclass with the students Attributes ---------- students: List a list of student-objects designation: String the designation of this schoolclass """ def __init__(self, designation: str) -> None: """ constructs the object :param: designation(string): the designation of this schoolclass """ self._designation = designation self._students = [] def add_student(self, student: Student) -> None: """ adds a student to the students list :param: student(Student) the student-object to add :raises: OverflowError: if the student-list is already full """ if self.count_students() < 20: self._students.append(student) student.school_class = self else: raise OverflowError def take_student(self, index: int) -> Student: """ returns the student identified by the index :param: index(int): the index of the student :raises: IndexError: if the index does not exist """ if index < self.count_students(): return self._students[index] raise IndexError def count_students(self) -> int: """ counts the number of students in the list :return: size of the list(int) """ return len(self._students) def show_student_list(self) -> str: """ shows a list of all student names """ output = '' for student in self._students: output += f'{student.name}\n' return output def show_student_report(self, name: str) -> str: """ Shows the grades for the student identified by his name :param name: The name of the student to be shown :return: """ print('----') for student in self._students: if student.name == name: return student.report.show_overview() return f'Student {name} nicht gefunden' @property def designation(self) -> str: """ returns the designation """ return self._designation
Erklärung
Mit der Bedingung if TYPE_CHECKING:
verhindern wir, dass die Imports während der Ausführung des Programms stattfinden.
Lediglich während dem Überprüfen der Datentypen (type checking) werden die weiteren Dateien einbezogen.
Dadurch können wir Datentypen in zweiseitigen Beziehungen verwenden, ohne dass ein zirkulärer Import auftritt.
Damit dies funktioniert, müssen from _
_future_
_ import annotations
und from typing import TYPE_CHECKING
importiert werden.
Die vollständige Lösung finden Sie unter https://github.com/templates-python/m320-lu09-a01-school/tree/typed.