Type Hints in Python: Typannotationen für besseren Code
Python ist dynamisch typisiert – trotzdem lohnen sich Type Hints. Du erfährst, wie Annotationen deinen Code lesbarer machen, Fehler früh aufdecken und deine Tools cleverer werden lassen.
Python ist eine dynamisch typisierte Sprache: Du musst nie angeben, ob eine Variable eine Zahl, ein String oder eine Liste ist. Das macht den Einstieg angenehm – kann aber in größeren Projekten schnell unübersichtlich werden. Genau hier kommen Type Hints (Typannotationen) ins Spiel. Seit Python 3.5 kannst du deinem Code sagen, welche Typen du erwartest. Wichtig: Diese Angaben sind reine Hinweise. Python führt zur Laufzeit keine Prüfung durch – aber Werkzeuge wie mypy, dein Editor und andere Entwickler profitieren enorm davon. In diesem Beitrag lernst du, wie Type Hints funktionieren und warum sie sich lohnen.
Die Grundlagen: Variablen und Funktionen annotieren
Am häufigsten begegnen dir Type Hints bei Funktionen. Nach jedem Parameter folgt ein Doppelpunkt mit dem erwarteten Typ, und nach der Klammer gibt ein Pfeil den Rückgabetyp an.
def begruessung(name: str, alter: int) -> str:
return f"Hallo {name}, du bist {alter} Jahre alt."
nachricht = begruessung("Anna", 30)
print(nachricht)Der Teil -> str sagt: Diese Funktion liefert einen String zurück. Auch einzelne Variablen kannst du annotieren, was besonders bei nicht offensichtlichen Typen hilft:
preis: float = 19.99
aktiv: bool = True
namen: list = ["Anna", "Ben", "Clara"]Beachte: Schreibst du begruessung("Anna", "dreißig"), läuft der Code trotzdem – Python beschwert sich nicht. Der Hinweis dient dir und deinen Tools, nicht dem Interpreter.
Komplexere Typen mit Listen, Dicts und Co.
Ein bloßes list verrät nicht, was in der Liste steckt. Seit Python 3.9 kannst du das direkt mit den eingebauten Typen präzisieren:
def durchschnitt(werte: list[float]) -> float:
return sum(werte) / len(werte)
def zaehle_woerter(text: str) -> dict[str, int]:
haeufigkeit: dict[str, int] = {}
for wort in text.split():
haeufigkeit[wort] = haeufigkeit.get(wort, 0) + 1
return haeufigkeitlist[float] bedeutet „eine Liste von Fließkommazahlen", dict[str, int] steht für „ein Dictionary mit String-Schlüsseln und Integer-Werten". So wird auf einen Blick klar, welche Datenstruktur eine Funktion erwartet und liefert. Nutzt du eine ältere Python-Version, importierst du List und Dict stattdessen aus dem typing-Modul.
Optionale Werte und mehrere Typen
Manchmal darf ein Wert auch None sein, oder eine Funktion akzeptiert mehrere Typen. Dafür gibt es Optional und die Union-Schreibweise mit dem senkrechten Strich (ab Python 3.10):
from typing import Optional
def finde_nutzer(user_id: int) -> Optional[str]:
datenbank = {1: "Anna", 2: "Ben"}
return datenbank.get(user_id) # gibt None zurück, falls nicht gefunden
# Moderne Union-Syntax: str ODER int
def verarbeite_id(id_wert: int | str) -> str:
return str(id_wert).strip()Optional[str] ist übrigens nichts anderes als eine Kurzform für str | None. Diese Annotationen sind besonders wertvoll: Sie machen sichtbar, dass ein Rückgabewert fehlen kann – und erinnern dich daran, diesen Fall im Code zu behandeln.
Statische Prüfung mit mypy
Der eigentliche Gewinn entsteht, wenn ein Type Checker deine Hinweise auswertet. Das bekannteste Werkzeug ist mypy. Du installierst es per pip und lässt es über deine Datei laufen:
pip install mypy
mypy mein_skript.pyAngenommen, du hast folgenden Fehler im Code:
def verdopple(zahl: int) -> int:
return zahl * 2
ergebnis = verdopple("5") # String statt int!Ohne Type Hints würde Python hier sogar "55" ausgeben – ein subtiler Bug. Mit mypy bekommst du dagegen schon vor dem Ausführen eine klare Warnung: Argument 1 to "verdopple" has incompatible type "str"; expected "int". So findest du ganze Fehlerklassen, bevor dein Programm überhaupt startet.
Eigene Typen lesbarer machen mit Aliassen
Wenn dieselbe komplexe Struktur immer wieder auftaucht, kannst du ihr einen Namen geben. Das reduziert Wiederholung und macht die Absicht deutlich:
Koordinate = tuple[float, float]
def entfernung(punkt_a: Koordinate, punkt_b: Koordinate) -> float:
dx = punkt_b[0] - punkt_a[0]
dy = punkt_b[1] - punkt_a[1]
return (dx**2 + dy**2) ** 0.5
start: Koordinate = (0.0, 0.0)
ziel: Koordinate = (3.0, 4.0)
print(entfernung(start, ziel)) # 5.0Statt überall tuple[float, float] zu schreiben, sprichst du jetzt von einer Koordinate – das liest sich fast wie natürliche Sprache und zeigt, worum es fachlich geht.
Fazit
Type Hints kosten dich ein paar zusätzliche Zeichen, geben dir aber viel zurück: lesbareren Code, bessere Autovervollständigung in deinem Editor, aussagekräftige Dokumentation und – zusammen mit mypy – ein Sicherheitsnetz gegen ganze Fehlerklassen. Du musst nicht sofort jedes Projekt komplett annotieren. Fang bei Funktionssignaturen an, denn dort ist der Nutzen am größten, und arbeite dich von dort weiter vor. Gerade wenn dein Code wächst oder du im Team arbeitest, wirst du die Klarheit schnell zu schätzen wissen. Probier es beim nächsten Skript einfach aus – dein zukünftiges Ich wird es dir danken.