Type Hints in Python: was sie bringen und wo mypy anschlägt
Annotationen prüfen zur Laufzeit gar nichts, sie machen den Code auch nicht schneller. Sie finden eine bestimmte Klasse von Fehlern, bevor jemand das Programm startet, und dafür lohnen sie sich.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Der Prüfer wird scharf gestellt, und danach traut sich niemand mehr an ihn
Der übliche erste Versuch sieht so aus: Jemand liest, dass Typen in Python inzwischen üblich sind, richtet den Prüfer ein, stellt ihn gleich auf die strengste Stufe und lässt ihn über das ganze Projekt laufen. Heraus kommen mehrere tausend Meldungen, davon ein großer Teil aus Modulen, die seit Jahren unverändert laufen, und ein weiterer Teil aus Fremdbibliotheken ohne Typinformationen. Damit ist die Einführung praktisch beendet, bevor sie begonnen hat.
Der zweite Fehlschlag ist stiller. Die Annotationen werden nachgetragen, aber niemand prüft sie. Dann stehen im Code Angaben, die zum Zeitpunkt des Schreibens richtig waren und beim nächsten Umbau nicht mitgezogen wurden. Eine falsche Angabe ist schlechter als keine, weil sie das Vertrauen kostet, auf dem der ganze Nutzen beruht, und weil der Editor daraufhin falsche Vorschläge macht.
Dazu kommt eine verbreitete Fehlvorstellung darüber, was Annotationen überhaupt tun. Sie prüfen zur Laufzeit nichts. Ein Aufruf mit einer Zeichenkette dort, wo eine Zahl steht, läuft genauso durch wie vorher, und die Angabe macht das Programm auch nicht schneller. Ihr Nutzen liegt vollständig davor: im Prüfer, im Editor und in dem, was andere Leute beim Lesen der Signatur verstehen.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Der Weg vom ersten Lauf bis zur verbindlichen Prüfung
Sechs Stationen, jede mit einem überprüfbaren Ergebnis. Die Reihenfolge ist nicht beliebig: Wer die Strenge vor der Grundlinie erhöht, arbeitet zwei Wochen an Meldungen, die niemand bestellt hat.
- 1
Den Nutzen und den Umfang festlegen
Entscheide, welche Frage die Annotationen beantworten sollen. Geht es darum, Fehler an den Schnittstellen zwischen Teams zu finden, dann sind die Modulgrenzen der Ort. Geht es um Vorschläge und sicheres Umbenennen im Editor, dann zählt Breite mehr als Tiefe. Geht es um eine Bibliothek, die andere benutzen, dann ist die öffentliche Schnittstelle das Ziel und der Rest nachrangig.
Geschafft, wenn: Eine Liste von drei bis fünf Modulen, an denen begonnen wird, und ein Satz dazu, warum genau diese.
- 2
Den Prüfer auswählen und mit den Voreinstellungen laufen lassen
mypy ist die älteste und am weitesten verbreitete Umsetzung und gilt als Bezugspunkt. Daneben stehen pyright aus dem Umfeld der Editorunterstützung, Pyrefly, das im Mai 2026 seine erste stabile Fassung erreicht hat, und ty, das sich noch in der Beta befindet und ausdrücklich keine stabile Schnittstelle zusagt. Die beiden jüngeren sind deutlich schneller, unterscheiden sich aber in der Auslegung einzelner Regeln. Lauf zuerst ohne besondere Einstellungen und schreib die Zahl der Meldungen auf.
Geschafft, wenn: Ein erster Lauf mit einer Zahl, die als Ausgangswert dient, und eine Entscheidung für ein Werkzeug.
- 3
Eine Grundlinie ziehen, damit der Lauf grün ist
Der Altbestand wird nicht repariert, sondern zunächst ausgenommen. In der Konfigurationsdatei lässt sich das modulweise einstellen, und einige Prüfer bringen dafür eine eigene Ausgangsliste mit, die bestehende Meldungen festhält und nur neue anzeigt. Wichtig ist, dass diese Ausnahmen sichtbar an einer Stelle stehen und nicht als verstreute Kommentare im Code, sonst weiß später niemand mehr, was noch offen ist.
Geschafft, wenn: Der Lauf ist grün, die Ausnahmen stehen gesammelt in der Konfiguration, und die Liste lässt sich abarbeiten.
- 4
Die Schnittstellen annotieren
Jetzt kommen die Signaturen dran: Parameter und Rückgabewerte der Funktionen, die von anderen Modulen aufgerufen werden, und die Datenstrukturen, die dort übergeben werden. Für zusammengesetzte Daten lohnt eine Dataclass oder ein TypedDict statt eines losen Dictionary, weil der Prüfer damit tatsächlich etwas anfangen kann. Wo eine Funktion auch None zurückgeben kann, gehört das ausdrücklich hin, denn dieser Fall ist der häufigste Fund überhaupt.
Geschafft, wenn: Die öffentlichen Funktionen der ausgewählten Module sind vollständig annotiert, und die ersten echten Fehler sind gefunden.
- 5
Die Prüfung in der CI verankern
Der Prüfer läuft ab jetzt in derselben Stufe wie die Tests und hält einen roten Lauf auf. Damit das nicht zur Bremse wird, hilft die Vorgabe, dass neu angelegte Dateien vollständig annotiert sein müssen, während bestehende in ihrem bisherigen Zustand bleiben dürfen. Der Prüfer bekommt dafür eine Einstellung pro Modul, und die Ausnahmeliste wird bei jedem Umbau eines Altmoduls um einen Eintrag kürzer.
Geschafft, wenn: Ein roter Lauf des Prüfers hält die Auslieferung auf, und die Zahl der ausgenommenen Module sinkt messbar.
- 6
Die Strenge modulweise erhöhen
Erst jetzt lohnt sich das Nachziehen der schärferen Einstellungen, und zwar Modul für Modul: keine Funktion ohne Annotation, kein stillschweigendes Any als Typ, keine ungenutzten type-ignore-Kommentare. Jede Verschärfung wird an einem Modul ausprobiert, bevor sie allgemein gilt. Wenn dabei eine Stelle auftaucht, die sich nicht sauber ausdrücken lässt, ist eine ausdrückliche Ausnahme mit Begründung im Code die ehrliche Lösung.
Geschafft, wenn: Die schärferen Einstellungen gelten für einen wachsenden Teil des Projekts, und jede Ausnahme trägt eine Begründung.
Fünf Fragen vor der ersten Annotation
- 01 Welchen Nutzen wollt ihr zuerst haben, weniger Fehler oder bessere Editorunterstützung?
- 02 Welche Module reden am meisten miteinander? Dort fangt ihr an.
- 03 Ist der erste Lauf grün, obwohl noch nichts annotiert ist?
- 04 Welche Fremdbibliotheken liefern gar keine Typinformationen?
- 05 Wird die Prüfung in derselben Stufe erzwungen wie die Tests?
Was du nach dieser Seite in der ersten Woche schaffst
Die Einführung ist eine Reihenfolgefrage. Sechs Punkte entscheiden darüber, ob nach zwei Wochen noch jemand am Thema arbeitet oder ob es in der Liste der guten Vorsätze verschwindet.
Zuerst festlegen, wofür ihr das macht
Für Fehler an Modulgrenzen, für bessere Vorschläge im Editor oder als verbindliche Beschreibung öffentlicher Schnittstellen. Aus dieser Antwort ergibt sich, wo ihr anfangt, und sie verhindert, dass jemand Zeit in Annotationen für private Hilfsfunktionen steckt, die niemand aufruft.
Mit einer Grundlinie starten statt mit Aufräumen
Der erste Lauf soll grün sein, auch wenn noch nichts annotiert ist. Dafür schaltest du die Prüfung für den Altbestand modulweise ab oder legst eine Ausgangsliste an, gegen die verglichen wird. Erst wenn der Lauf grün ist, kann er in die CI-Umgebung, und erst dann fällt eine neue Meldung überhaupt auf.
Von außen nach innen annotieren
Anfangen bei den Signaturen, die zwischen Modulen aufgerufen werden, und bei den Datenstrukturen, die dort hin und her gehen. Diese wenigen Stellen liefern den größten Teil des Nutzens, weil dort die Missverständnisse sitzen. Lokale Variablen brauchen fast nie eine Angabe, der Prüfer leitet sie ohnehin ab.
Neue Dateien sofort streng behandeln
Was neu entsteht, wird vollständig annotiert und streng geprüft. Das ist die einzige Regel, die dafür sorgt, dass die Menge an ungeprüftem Code schrumpft, statt weiterzuwachsen, und sie kostet beim Schreiben so gut wie nichts, weil die Information ohnehin im Kopf ist.
Fremdbibliotheken früh klären
Ein großer Teil der ersten Meldungen kommt gar nicht aus eurem Code, sondern aus Bibliotheken ohne Typinformationen. Für viele davon gibt es eigene Stub-Pakete. Was übrig bleibt, wird ausdrücklich als ungeprüft gekennzeichnet, damit die Meldungen aus eurem Code sichtbar bleiben.
Die Prüfung genauso ernst nehmen wie die Tests
Solange der Prüfer nur lokal läuft, wandert das Ergebnis in den Hintergrund. Er gehört in dieselbe Stufe wie die Tests, mit demselben Anspruch, dass ein roter Lauf aufgehalten wird. Sonst sammeln sich Meldungen an, bis wieder niemand mehr hinsieht.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Was Annotationen leisten und was sie ausdrücklich nicht tun
Der greifbarste Nutzen ist eine bestimmte Fehlerklasse, die vor dem Start gefunden wird: ein Wert, der auch None sein kann und an einer Stelle benutzt wird, die damit nicht rechnet. Dazu kommen falsche Argumentzahlen, vertauschte Parameter und Aufrufe, die nach einer Umbenennung übrig geblieben sind. In gewachsenem Code ist der erste Punkt fast immer der ergiebigste, weil er sich sonst erst in der Produktion zeigt.
Der zweite Nutzen ist die Werkzeugunterstützung. Ein Editor kann mit Annotationen sinnvolle Vorschläge machen, Umbenennungen über Modulgrenzen hinweg durchziehen und beim Springen zur Definition richtig raten. Wer das einmal in einem vollständig annotierten Modul erlebt hat, will nicht zurück, und dieser Effekt ist der Grund, warum die Einführung in Teams meistens von unten kommt und nicht von oben.
Nicht geleistet wird das, was der Name nahelegt. Zur Laufzeit prüft Python nichts. Eine falsche Übergabe führt zu keinem Fehler, solange der Code damit zufällig arbeiten kann. Wer echte Prüfung an der Systemgrenze braucht, also bei Eingaben aus dem Netz oder aus einer Datei, braucht dafür eine Bibliothek, die Werte tatsächlich validiert. Auch schneller wird nichts: Annotationen sind Beschreibung, nicht Optimierung.
Welcher Prüfer und warum das inzwischen eine echte Frage ist
mypy ist die Umsetzung, an der sich die Sprachfestlegungen entwickelt haben, und in Zweifelsfällen die Referenz. Der Preis ist die Geschwindigkeit: Auf einem großen Projekt kann ein vollständiger Lauf mehrere Minuten dauern, was der Grund ist, warum viele Teams ihn irgendwann nur noch in der CI-Umgebung laufen lassen und nicht mehr beim Schreiben.
Daneben sind zwei jüngere Werkzeuge in Rust entstanden, die genau dort ansetzen. Pyrefly kommt von Meta und hat im Mai 2026 die Version 1.0 erreicht, wird also als produktionsreif bezeichnet und ist in großen Codebasen im Einsatz. ty kommt von Astral, ist als Beta gekennzeichnet, steht bei einer Fassung aus der Reihe 0.0.x und sagt ausdrücklich zu, dass sich Verhalten und Meldungen zwischen zwei Fassungen ändern können. Beide sind um ein Vielfaches schneller als mypy, was den Unterschied zwischen einem Lauf nach dem Speichern und einem Lauf in der Mittagspause ausmacht.
Für die Auswahl zählt weniger die Geschwindigkeit als die Frage, wie die Werkzeuge Zweifelsfälle behandeln. Sie legen einzelne Regeln unterschiedlich streng aus, und ein Wechsel bedeutet deshalb regelmäßig eine neue Runde an Meldungen. Wer mehrere Prüfer nebeneinander laufen lässt, bekommt die Vereinigungsmenge und damit mehr Arbeit als Nutzen. Ein Werkzeug pro Projekt, verbindlich in der Konfiguration festgehalten, ist die pflegeleichtere Entscheidung.
Wo es im Bestand tatsächlich klemmt
Die erste Hürde sind dynamische Muster. Funktionen, die beliebige benannte Argumente entgegennehmen und weiterreichen, Klassen, deren Attribute erst zur Laufzeit entstehen, und Dekoratoren, die die Signatur der dekorierten Funktion verändern. Für Dekoratoren gibt es inzwischen ausdrückliche Sprachmittel, mit denen sich die Signatur durchreichen lässt, für die anderen Fälle ist die ehrlichste Antwort oft, den betreffenden Teil umzubauen statt ihn zu beschreiben.
Die zweite Hürde sind Frameworks, die stark mit Metaklassen und dynamisch erzeugten Attributen arbeiten. Ein Datenbankmodell, dessen Felder erst beim Laden der Klasse entstehen, ist für einen Prüfer schwer zu erfassen. Verbreitete Rahmenwerke liefern dafür eigene Erweiterungen für den Prüfer mit, und die gehören in die Konfiguration, bevor jemand anfängt, Meldungen einzeln zu unterdrücken.
Die dritte Hürde ist die Ansteckung durch Any. Sobald ein Wert aus einer nicht typisierten Bibliothek kommt, gilt er für den Prüfer als Any, und alles, was daraus abgeleitet wird, ebenfalls. Der Prüfer meldet dann keinen Fehler mehr, prüft aber auch nichts. Deshalb lohnt es sich, an den Systemgrenzen ausdrücklich zu sagen, welcher Typ dort erwartet wird, und den Rest darauf aufzubauen. Für Schnittstellen, die nur ein bestimmtes Verhalten verlangen, ist ein Protokoll dabei fast immer die passendere Beschreibung als eine gemeinsame Basisklasse.
Annotationen, die zur Laufzeit gelesen werden
Es gibt einen wichtigen Sonderfall: Bibliotheken, die Annotationen nicht nur beschreiben, sondern auswerten. Datenklassen leiten daraus ihre Felder ab, Validierungsbibliotheken erzeugen daraus Prüfungen, und Webrahmenwerke bauen daraus die Beschreibung ihrer Schnittstelle. In diesen Fällen ist eine Annotation eben doch mehr als Dokumentation, und ein Tippfehler darin wird zu einem Laufzeitfehler.
Genau daran hängt eine Änderung, die mit Python 3.14 gekommen ist. Nach PEP 649 werden Annotationen nicht mehr beim Definieren ausgewertet, sondern erst beim Zugriff darauf. Das löst zwei alte Ärgernisse: Vorwärtsverweise auf eine Klasse, die weiter unten definiert wird, funktionieren ohne Anführungszeichen, und Typen, die nur für die Prüfung importiert werden, führen nicht mehr zu Zirkelimporten. Der ältere Weg über den entsprechenden Import aus dem future-Modul wird damit auf Sicht überflüssig.
Für den Alltag heißt das zweierlei. Erstens lohnt es sich, Importe, die ausschließlich für Annotationen gebraucht werden, in den dafür vorgesehenen Block zu stellen, der nur beim Prüfen wahr ist. Zweitens gehört bei jeder Bibliothek, die Annotationen zur Laufzeit ausliest, in der Dokumentation nachgesehen, wie sie damit umgeht, denn sie muss die Auswertung ausdrücklich anstoßen, statt sich auf ein fertiges Wörterbuch zu verlassen.
Dazu passende Kurse
Wenn Annotationen Teil eurer Vorgaben werden sollen, sorgen Python-Kurse mit Blick auf Wartbarkeit dafür, dass alle dasselbe darunter verstehen.
Weil Typen nur helfen, wenn der Schnitt der Module stimmt, gehören Kurse zu sauberem Aufbau von Programmen zur selben Baustelle.
Wie sicher bist du beim Thema wirklich?
Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.
Wo du genau das übst
Sehr umfangreicher Überblick über Zusammenhänge und Anwendungsbereiche. Sehr zu empfehlen.
Effektives, gemeinsames Erarbeiten der Aufgaben mit vielen praktischen Tipps.
Sehr guter Trainer und gute Aufbereitung der Inhalte und auch eingehen auf Fragen der Beteiligten.
Häufige Fragen
Lohnen sich Type Hints in einem kleinen Projekt überhaupt?
Machen Annotationen den Code langsamer?
Müssen wir wirklich alles annotieren?
Können wir den Prüfer wechseln, wenn wir uns einmal entschieden haben?
Was machen wir mit Bibliotheken, die keine Typinformationen liefern?
Deine Ansprechpartner
Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.
Yves Hoppe
Weiterbildung & Beratung
Hilft dir, aus dem Programmierung-Programm den passenden Kurs für deinen Stand zu finden.
Norbert Jansen
Beratung & Inhouse
Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.
Lesbaren Python-Code an eigenen Beispielen üben
Im Clean-Code-Kurs mit Python bei cmt gehst du Signaturen, Datenstrukturen und Schnittstellen an Code durch, den du selbst mitbringst, und siehst dabei, welche Annotation wirklich etwas beiträgt.