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

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.

  • modul/m320_2024/learningunits/lu09/loesungen/schulverwaltung_typed.txt
  • Zuletzt geändert: 2024/10/02 15:09
  • von msuter