LU09c - Zweiseitige Mehrfachbeziehung mit Types

Beim Einsatz von Types führen zweiseitige Beziehungen einem zirkulären Import. Diese Seite beschreibt einen Lösungsansatz.

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.

Ich habe das Codebeispiel mit den Feriendestinationen und Personen um Types ergänzt.

from holiday_destination import HolidayDestination
 
 
class Person:
    def __init__(self, name):
        ...
 
    def __str__(self) -> str:
        ...
 
    def add_destination(self, destination: HolidayDestination) -> None:
        if not destination in self._destinations:
            self._destinations.append(destination)
            destination.add_person(self)
 
    def remove_destination(self, destination: HolidayDestination) -> None:
        if destination in self._destinations:
            self._destinations.remove(destination)
            destination.remove_person(self)
 
from person import Person
 
 
class HolidayDestination:
    def __init__(self, location):
        ...
 
    def __str__(self) -> str:
        ...
 
    def add_person(self, person: Person) -> None:
        if not person in self._people:
            self._people.append(person)
            person.add_destination(self)
 
    def remove_person(self, person: Person) -> None:
        if person in self._people:
            self._people.remove(person)
            person.remove_destination(self)

Dieser Code kann nicht ausgeführt werden, da sich beide Klassen gegenseitig importieren möchten.

  1. HolidayDestination importiert die Klasse Person.
  2. Person importiert seinerseits die Klasse HolidayDestination, welche wiederum Person importieren will.

Wir müssen verhinden, dass sich die Klassen gegenseitig importieren. Gleichzeitig wird aber der Import der jeweils anderen Klasse für das TypeChecking benötigt. Es klingt zunächst nach einem unlösbaren Dilemma.

Wenn wir den Ablauf bei der Ausführung eines Pythonskripts genau anschauen, zeichnet sich eine Lösung ab. Dazu muss man verstehen, dass …

  • … das TypeChecking vor der eigentlichen Ausführung des Programms stattfindet,
  • … TypeChecking kein Problem mit zirkulären Imports hat.

Hilfe naht in Form der Bibliothek „typing“. Diese bietet eine Möglichkeit, den Import nur für das TypeChecking zu verwenden.

from __future__ import annotations # required for Python < 3.14
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from person import Person
 
 
class HolidayDestination:
    ...
 
 
 
if TYPE_CHECKING:
    from holyday_destination import HolidayDestination
 
class Person:
    ...
 

Mit der Bedingung if TYPE_CHECKING: erreichen wir, dass der Import nur für das TypeChecking durchgeführt wird. Für die eigentliche Ausführung des Programms wird die jeweils andere Klasse nicht importiert.

Falls Sie eine Python-Version 3.13 oder älter verwenden, brauchen Sie ausserdem from future import annotations


Marcel Suter

  • de/modul/m320_2024/learningunits/lu09/zweiseitige_types.txt
  • Zuletzt geändert: 2026/09/10 06:09
  • von msuter