EMZETT.
Login

Kurz: Python ist dynamisch typisiert: Eine Variable kann nacheinander Zahl, Text und Liste enthalten. Mit Typ-Hints (Typannotationen) schreibst du dazu, welche Typen du erwartest.

Teil des Kurses Python

Kapitel 40 von 44 im Kurs Python (Abschnitt „Professionell arbeiten“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Python ist dynamisch typisiert: Eine Variable kann nacheinander Zahl, Text und Liste enthalten. Mit Typ-Hints (Typannotationen) schreibst du dazu, welche Typen du erwartest. Python führt sie nicht aus, aber Editoren und Prüfwerkzeuge wie mypy oder pyright finden damit Fehler, bevor das Programm läuft, und der Code ist besser lesbar.

Grundlagen

name: str = "Mia"
alter: int = 17
preis: float = 9.99
aktiv: bool = True
 
def begruessen(name: str, laut: bool = False) -> str:
    text = f"Hallo {name}"
    return text.upper() if laut else text
 
print(begruessen("Tom"))
print(begruessen("Tom", laut=True))
print(begruessen.__annotations__)

Ausgabe:

Hallo Tom
HALLO TOM
{'name': <class 'str'>, 'laut': <class 'bool'>, 'return': <class 'str'>}

Nach dem Doppelpunkt steht der Typ eines Parameters, nach dem Pfeil -> der Typ des Rückgabewerts. None als Rückgabetyp bedeutet “gibt nichts zurück”.

Sammlungen

Seit Python 3.9 schreibst du die eingebauten Typen direkt mit eckigen Klammern:

def mittelwert(zahlen: list[float]) -> float:
    return sum(zahlen) / len(zahlen)
 
def zaehle(woerter: list[str]) -> dict[str, int]:
    ergebnis: dict[str, int] = {}
    for w in woerter:
        ergebnis[w] = ergebnis.get(w, 0) + 1
    return ergebnis
 
punkt: tuple[int, int] = (3, 4)
ids: set[int] = {1, 2, 3}
 
print(mittelwert([1, 2, 3, 4]))
print(zaehle(["a", "b", "a"]))

Ausgabe:

2.5
{'a': 2, 'b': 1}
HintBedeutung
list[int]Liste von ganzen Zahlen
dict[str, float]Dictionary von Text auf Kommazahl
tuple[int, str]Tupel aus genau zwei Elementen
tuple[int, ...]Tupel beliebiger Länge aus ints
set[str]Menge von Texten

Optional und Vereinigungen

Kann ein Wert auch None sein oder zwei Typen haben, schreibst du | (ab Python 3.10):

def finde(liste: list[str], gesucht: str) -> int | None:
    for i, eintrag in enumerate(liste):
        if eintrag == gesucht:
            return i
    return None
 
def verdopple(x: int | float) -> int | float:
    return x * 2
 
print(finde(["a", "b"], "b"), finde(["a", "b"], "z"))
print(verdopple(2), verdopple(2.5))

Ausgabe:

1 None
4 5.0

Weitere nützliche Typen

from typing import Any, Callable, Literal, TypedDict
 
def anwenden(f: Callable[[int], int], wert: int) -> int:
    return f(wert)
 
def richtung(r: Literal["links", "rechts"]) -> str:
    return f"geh nach {r}"
 
class Nutzer(TypedDict):
    name: str
    alter: int
 
n: Nutzer = {"name": "Mia", "alter": 17}
print(anwenden(lambda x: x + 1, 4))
print(richtung("links"))
print(n["name"])

Ausgabe:

5
geh nach links
Mia
TypBedeutung
Anybeliebig (schaltet die Prüfung ab)
Callable[[A, B], R]Funktion mit Parametern A, B und Rückgabe R
Literal["a", "b"]nur diese festen Werte
TypedDictDictionary mit festen Schlüsseln
Iterable[T], Sequence[T]allgemeine Sammlungen (aus collections.abc)

Eigene Klassen und Generics

from dataclasses import dataclass
from typing import TypeVar
 
T = TypeVar("T")
 
@dataclass
class Punkt:
    x: int
    y: int
 
def abstand(a: Punkt, b: Punkt) -> float:
    return ((a.x - b.x) ** 2 + (a.y - b.y) ** 2) ** 0.5
 
def erstes(liste: list[T]) -> T:      # T steht für "irgendein Typ"
    return liste[0]
 
print(abstand(Punkt(0, 0), Punkt(3, 4)))
print(erstes([10, 20]), erstes(["x", "y"]))

Ausgabe:

5.0
10 x

Ab Python 3.12 geht es kürzer: def erstes[T](liste: list[T]) -> T: braucht keine TypeVar-Zeile mehr.

Prüfen mit mypy

Typ-Hints ändern das Laufzeitverhalten nicht. Fehler findest du mit einem Prüfprogramm:

pip install mypy
mypy meine_datei.py
# mypy würde hier melden: Argument 1 has incompatible type "str"; expected "int"
def doppelt(x: int) -> int:
    return x * 2
 
print(doppelt("ab"))

Ausgabe:

abab

Das Programm läuft trotzdem, weil Python die Hints nicht erzwingt. Erst mypy schlägt Alarm.

Tipp

Fange bei neuen Projekten gleich mit Hints an, zumindest bei Funktionssignaturen. Das lohnt sich vor allem bei größeren Programmen und im Team.

Merke

  • x: int annotiert Variablen, -> str den Rückgabewert
  • list[int], dict[str, int], tuple[int, int] für Sammlungen
  • int | None für optionale Werte
  • Hints werden nicht erzwungen; mypy oder pyright prüfen sie
  • Callable, Literal, TypedDict, Any für Sonderfälle

Übungsaufgabe

Annotiere eine Funktion teile(text: ..., trenner: ...), die einen Text an einem Trenner teilt und die Teile als Liste zurückgibt, und eine Funktion, die den längsten Text aus einer Liste oder None liefert.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Dataclasses und Properties

Weiter: Tests mit unittest und pytest

Alle Kapitel: Python im Überblick