12 Typannotationen

Typannotation (Type Annotation) ist eine Möglichkeit in Python, den erwarteten Typ von Variablen, Funktionsparametern und Rückgabewerten anzugeben.

Vorteile der Typannotation

Obwohl Python eine dynamisch typisierte Sprache ist, erlaubt die Typannotation eine bessere Lesbarkeit, Wartbarkeit und eine reduzierte Fehleranfälligkeit im Code.

1 Grundlagen der Typannotation

Typannotation wird mit einem Doppelpunkt : und dem Typnamen gemacht. Der Rückgabetyp einer Funktion wird mit -> angegeben.

1.1 Beispiel:

def addiere(x: int, y: int) -> int:
    return x + y

In diesem Beispiel wird angegeben, dass sowohl x als auch y vom Typ int sind und die Funktion einen int zurückgibt.

2 Typannotation bei Variablen

name: str = "Anna"
alter: int = 30
aktiv: bool = True

3 Optionaler Typ

Manchmal kann eine Variable auch None sein. Dafür verwendet man Optional:

from typing import Optional

def finde_benutzer(id: int) -> Optional[str]:
    if id == 1:
        return "Anna"
    return None

4 Any

Der Typ Any aus dem typing-Modul signalisiert, dass jede Art von Wert erlaubt ist. Dies ist hilfreich, wenn der genaue Typ nicht bekannt oder variabel ist.

from typing import Any

def drucke_wert(wert: Any) -> None:
    print(wert)

5 Callable

Callable wird verwendet, um Funktionen als Parameter oder Rückgabewerte zu typisieren.

from typing import Callable

def verarbeite(funktion: Callable[[int, int], int]) -> int:
    return funktion(2, 3)

In diesem Beispiel ist funktion eine Funktion, die zwei int-Werte nimmt und einen int zurückgibt.

6 Typannotation in Klassen

Auch in Klassen können Typannotationen verwendet werden:

class Person:
    name: str
    alter: int

    def __init__(self, name: str, alter: int) -> None:
        self.name = name
        self.alter = alter

6.1 Verweis auf eigene Klasse als Typ

Will man innerhalb einer Klasse auf die eigene Klasse verweisen (z. B. bei einer Methode, die ein Objekt der gleichen Klasse zurückgibt), verwendet man einen String (um zirkuläre Importe zu vermeiden) oder ab Python 3.11 from __future__ import annotations:

class Knoten:
    def __init__(self, wert: int, nachfolger: 'Knoten' = None) -> None:
        self.wert = wert
        self.nachfolger = nachfolger

Ab Python 3.11:

from __future__ import annotations

class Knoten:
    def __init__(self, wert: int, nachfolger: Knoten = None) -> None:
        self.wert = wert
        self.nachfolger = nachfolger

7 Typalias

Man kann eigene Typen definieren, um komplexe Strukturen lesbarer zu machen:

from typing import List, Tuple

Koordinaten = Tuple[float, float]
Pfad = List[Koordinaten]

8 Warum Typannotationen verwenden?

  • Lesbarkeit: Andere Entwickler verstehen schneller, was erwartet wird.
  • Wartbarkeit: Änderungen im Code sind leichter nachzuvollziehen.
  • Fehlervermeidung: Tools wie Mypy, Pyright/Pylance oder IDEs können Fehler frühzeitig erkennen.
  • Dokumentation: Typen fungieren als explizite Dokumentation des Codes.
Kein Zwang zur Typisierung

Python bleibt trotz Typannotationen dynamisch. Die Typangaben werden zur Laufzeit nicht erzwungen. Sie dienen lediglich als Hilfe für Entwickler und Werkzeuge.

def echo(text: str) -> str:
	return text

# Funktioniert trotzdem, obwohl ein falscher Typ übergeben wird
print(echo(123))  # Ausgabe: 123

9 Typenvergleich

Typen vergleichen kann man mit den Funktionen type() und isinstance().

Beispiel:

from collections import namedtuple

Point = namedtuple('Punkt', ['x', 'y'])
p = Point(2, 3)

if type(p) == tuple:
    print('P ist ein Tupel.')  # Wird nicht ausgegeben!

if isinstance(p, tuple):
    print('P ist ein Tupel.')
Tip

Es ist in der Regel besser, isinstance() anstelle eines direkten Vergleichs mit type() zu verwenden, weil isinstance() auch Vererbungen berücksichtigt.

  • type() gibt die exakte Klasse des Objekts p zurück, nämlich Point. Daher wird in dem Beispiel der Vergleich falsch ausgewertet.
  • isinstance() überprüft, ob p eine Instanz von tuple oder einer Unterklasse davon ist. Da namedtuple eine Unterklasse von tuple ist, gibt isinstance(p, tuple) True zurück.

10 Fazit

Typannotationen machen Python-Code robuster, verständlicher und besser wartbar, ohne die Flexibilität der Sprache einzuschränken. Es lohnt sich, sie konsequent zu verwenden, besonders bei größeren Projekten.