🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Python Type Hints Complete Guide 2026: mypy, Protokolle und erweiterte Muster

⏱️5 min read  ·  938 words

Python-Typhinweise verändern die Art und Weise, wie Sie Python-Code schreiben, lesen und verwalten. Typhinweise wurden in Python 3.5 hinzugefügt und durch 3.12+ erheblich verbessert und sind heute eine Standardpraxis in der professionellen Python-Entwicklung. Dieser Leitfaden deckt alles ab, von den Grundlagen bis hin zu fortgeschrittenen Mustern.

Warum Typhinweise im Jahr 2026 wichtig sind

Python bleibt zur Laufzeit dynamisch typisiert, aber Typhinweise bieten Folgendes:

  • IDE-Intelligenz– Autovervollständigung, Go-to-Definition, Refactoring in PyCharm und VS Code
  • Statische Analyse– mypy und Pyright erkennen Fehler vor der Laufzeit
  • Dokumentation– Funktionssignaturen erklären, was hineingeht und was herauskommt
  • Vertrauen im Maßstab— sicheres Refactoring in großen Codebasen

Grundlegende Anmerkungen

from typing import Optional, Union
from datetime import datetime

# Variable annotations
name: str = "Alice"
age: int = 30
active: bool = True
scores: list[float] = [9.5, 8.7, 9.2]
config: dict[str, str] = {"env": "prod", "region": "us-east-1"}

# Function annotations
def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}!"

def find_user(user_id: int) -> dict[str, str] | None:
    # Python 3.10+ union syntax (| instead of Union[])
    ...

# None return type
def log(message: str) -> None:
    print(f"[LOG] {message}")

Sammlungen und Generika

from typing import Sequence, Mapping, Iterator, Generator
from collections.abc import Callable

# Built-in generics (Python 3.9+)
def first(items: list[int]) -> int | None:
    return items[0] if items else None

def merge(a: dict[str, int], b: dict[str, int]) -> dict[str, int]:
    return {**a, **b}

# Sequence — more general than list
def count_items(items: Sequence[str]) -> int:
    return len(items)

# Callable type
def apply(func: Callable[[int, int], int], a: int, b: int) -> int:
    return func(a, b)

result = apply(lambda x, y: x + y, 3, 4)  # 7

# Generator type
def fibonacci() -> Generator[int, None, None]:
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# TypeVar for generic functions
from typing import TypeVar
T = TypeVar("T")

def identity(value: T) -> T:
    return value

def first_item(items: list[T]) -> T | None:
    return items[0] if items else None

TypedDict und Datenklassen

from typing import TypedDict, Required, NotRequired
from dataclasses import dataclass, field

# TypedDict — typed dictionaries
class UserDict(TypedDict):
    id: int
    name: str
    email: str

class PartialUser(TypedDict, total=False):
    id: int
    name: str
    email: str

# With Required/NotRequired (Python 3.11+)
class Config(TypedDict):
    host: Required[str]
    port: Required[int]
    debug: NotRequired[bool]

# Dataclass — cleaner than TypedDict for classes
@dataclass
class Product:
    id: int
    name: str
    price: float
    tags: list[str] = field(default_factory=list)
    active: bool = True

    def apply_discount(self, percent: float) -> "Product":
        return Product(
            id=self.id,
            name=self.name,
            price=self.price * (1 - percent / 100),
            tags=self.tags,
            active=self.active
        )

# frozen=True for immutability
@dataclass(frozen=True)
class Point:
    x: float
    y: float

Protokoll – Strukturelle Subtypisierung

Protokolle definieren Schnittstellen ohne Vererbung:

from typing import Protocol, runtime_checkable

@runtime_checkable
class Drawable(Protocol):
    def draw(self) -> None: ...
    def get_area(self) -> float: ...

class Circle:
    def __init__(self, radius: float):
        self.radius = radius

    def draw(self) -> None:
        print(f"Drawing circle r={self.radius}")

    def get_area(self) -> float:
        import math
        return math.pi * self.radius ** 2

class Rectangle:
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def draw(self) -> None:
        print(f"Drawing rect {self.width}x{self.height}")

    def get_area(self) -> float:
        return self.width * self.height

def render_all(shapes: list[Drawable]) -> None:
    for shape in shapes:
        shape.draw()
        print(f"Area: {shape.get_area():.2f}")

# Works without inheritance — structural compatibility
shapes: list[Drawable] = [Circle(5.0), Rectangle(3.0, 4.0)]
render_all(shapes)

Literal- und Finaltypen

from typing import Literal, Final, TypeAlias

# Literal — restrict to specific values
def set_direction(direction: Literal["north", "south", "east", "west"]) -> None:
    print(f"Moving {direction}")

set_direction("north")  # OK
set_direction("up")     # mypy error!

# Final — constants that cannot be reassigned
MAX_RETRIES: Final = 3
BASE_URL: Final[str] = "https://api.example.com"

# TypeAlias — named type aliases (Python 3.10+)
Vector: TypeAlias = list[float]
Matrix: TypeAlias = list[Vector]
JSON: TypeAlias = dict[str, "JSONValue"]
JSONValue: TypeAlias = str | int | float | bool | None | list["JSONValue"] | JSON

ParamSpec und TypeVarTuple (Erweitert)

from typing import ParamSpec, TypeVar, Callable
import functools
import time

P = ParamSpec("P")
R = TypeVar("R")

# Type-safe decorator that preserves signature
def retry(max_attempts: int = 3):
    def decorator(func: Callable[P, R]) -> Callable[P, R]:
        @functools.wraps(func)
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    time.sleep(2 ** attempt)
            raise RuntimeError("unreachable")
        return wrapper
    return decorator

@retry(max_attempts=3)
def fetch_data(url: str, timeout: int = 30) -> dict:
    import requests
    return requests.get(url, timeout=timeout).json()

mypy- und Pyright-Konfiguration

# pyproject.toml

[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_ignores = true
no_implicit_reexport = true

# Pyright (pyrightconfig.json or pyproject.toml)
[tool.pyright]
pythonVersion = "3.12"
typeCheckingMode = "strict"
reportMissingTypeStubs = false

Geben Sie Verengungsmuster ein

from typing import assert_never

type Shape = Circle | Rectangle | Triangle  # Python 3.12 type statement

def get_area(shape: Shape) -> float:
    match shape:
        case Circle(radius=r):
            return 3.14159 * r * r
        case Rectangle(width=w, height=h):
            return w * h
        case Triangle(base=b, height=h):
            return 0.5 * b * h
        case _ as unreachable:
            assert_never(unreachable)  # exhaustiveness check

Zusammenfassung

Hinweise zum Python-Typ im Jahr 2026 sind für die berufliche Entwicklung unerlässlich. Verwenden Sie sie in allen neuen Codes, aktivieren Sie die strenge Mypy/Pyright-Prüfung und nutzen Sie das Protokoll für Duck-Typing. Die Auswirkung auf die Laufzeitleistung ist gleich Null – Typen werden zur Ausführungszeit gelöscht.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা