Python – 08 Type Hints

Python – 08 Type Hints

Voraussetzungen

Bevor du mit diesem Modul startest, solltest du bereits vertraut sein mit:

Optionales Bonusmaterial

Dieser Abschnitt ist optional und dient der Vertiefung!

Type Hints sind nicht zwingend erforderlich für die Grundlagen-Ausbildung. Sie sind jedoch Best Practice in professionellem Python-Code und besonders nützlich, wenn du:

  • Größere Projekte entwickelst
  • Mit anderen Entwicklern zusammenarbeitest
  • Fehler frühzeitig erkennen möchtest

Empfehlung: Absolviere erst Python – 01 Kommentare Variablen Strings bis Python – 07 Funktionen und Methoden, bevor du dich mit Type Hints beschäftigst.

Was sind Type Hints?

Type Hints wurden in Python 3.5 eingeführt und ermöglichen es, Datentypen für Variablen, Funktionsparameter und Rückgabewerte zu spezifizieren. Sie verbessern die Lesbarkeit des Codes und helfen bei der Fehlersuche.

Grundlegende Syntax

Variablen mit Type Hints

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from typing import List, Dict, Optional, Union

# Einfache Typen
name: str = "Alice"
age: int = 30
height: float = 1.75
is_student: bool = True

# Listen und Dictionaries
numbers: List[int] = [1, 2, 3, 4, 5]
grades: Dict[str, int] = {"Math": 90, "English": 85}

# Optional (kann None sein)
middle_name: Optional[str] = None

# Union (mehrere mögliche Typen)
user_id: Union[int, str] = "user123"

Funktionen mit Type Hints

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def greet(name: str) -> str:
    """Begrüßt eine Person mit ihrem Namen."""
    return f"Hallo, {name}!"

def calculate_area(length: float, width: float) -> float:
    """Berechnet die Fläche eines Rechtecks."""
    return length * width

def process_data(data: List[int]) -> Dict[str, int]:
    """Verarbeitet eine Liste von Zahlen."""
    return {
        "sum": sum(data),
        "count": len(data),
        "max": max(data) if data else 0
    }

# Funktion ohne Rückgabewert
def print_info(name: str, age: int) -> None:
    print(f"{name} ist {age} Jahre alt.")

Erweiterte Type Hints

Generic Types und TypeVar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from typing import TypeVar, Generic, List

T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: List[T] = []
    
    def push(self, item: T) -> None:
        self._items.append(item)
    
    def pop(self) -> T:
        return self._items.pop()
    
    def is_empty(self) -> bool:
        return len(self._items) == 0

# Verwendung
int_stack: Stack[int] = Stack()
string_stack: Stack[str] = Stack()

Callable

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from typing import Callable

def apply_operation(x: int, y: int, operation: Callable[[int, int], int]) -> int:
    """Wendet eine Operation auf zwei Zahlen an."""
    return operation(x, y)

def add(a: int, b: int) -> int:
    return a + b

result: int = apply_operation(5, 3, add)  # result = 8

Protocols (Duck Typing)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None:
        ...

class Circle:
    def draw(self) -> None:
        print("Zeichne einen Kreis")

class Square:
    def draw(self) -> None:
        print("Zeichne ein Quadrat")

def render_shape(shape: Drawable) -> None:
    shape.draw()

# Funktioniert mit allen Objekten, die eine draw() Methode haben
circle = Circle()
square = Square()
render_shape(circle)  # Duck Typing
render_shape(square)

Moderne Type Hints (Python 3.9+)

Built-in Collections

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Statt typing.List, typing.Dict, etc.
def process_scores(scores: list[int]) -> dict[str, float]:
    return {
        "average": sum(scores) / len(scores),
        "min": float(min(scores)),
        "max": float(max(scores))
    }

# Verschachtelte Typen
student_grades: dict[str, list[int]] = {
    "Alice": [90, 85, 92],
    "Bob": [78, 82, 88]
}

Union mit |

1
2
3
4
5
6
7
8
# Statt Union[int, str]
def process_id(user_id: int | str) -> str:
    return str(user_id)

# Optional mit |
def get_user_name(user_id: int) -> str | None:
    # Gibt entweder einen Namen oder None zurück
    return "Alice" if user_id == 1 else None

Klassen und Dataclasses

Klassen mit Type Hints

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from dataclasses import dataclass
from typing import ClassVar

class Person:
    def __init__(self, name: str, age: int) -> None:
        self.name: str = name
        self.age: int = age
        self._friends: list[str] = []
    
    def add_friend(self, friend: str) -> None:
        self._friends.append(friend)
    
    def get_friends(self) -> list[str]:
        return self._friends.copy()

# Dataclass (automatische __init__, __repr__, etc.)
@dataclass
class Student:
    name: str
    student_id: int
    grades: list[int]
    is_active: bool = True
    
    # Class variable
    school_name: ClassVar[str] = "Python University"
    
    def calculate_average(self) -> float:
        return sum(self.grades) / len(self.grades) if self.grades else 0.0

Best Practices

1. Schrittweise Einführung

1
2
3
4
5
# Beginne mit kritischen Funktionen
def calculate_tax(income: float, rate: float) -> float:
    return income * rate

# Erweitere nach und nach

2. mypy für Typüberprüfung

1
2
3
4
5
# Installation
pip install mypy

# Überprüfung
mypy my_script.py

3. Type Aliases für Komplexität

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from typing import TypeAlias

# Alias für komplexe Typen
UserId: TypeAlias = int
UserData: TypeAlias = dict[str, str | int]
DatabaseConnection: TypeAlias = object  # Placeholder

def get_user(user_id: UserId, db: DatabaseConnection) -> UserData:
    # Implementation
    return {"name": "Alice", "age": 30}

4. Verwendung von Any sparsam

1
2
3
4
5
6
7
from typing import Any

# Vermeide Any wenn möglich
def process_unknown(data: Any) -> Any:  # Nicht ideal
    return data

# Besser: Spezifische Typen oder Generics verwenden

Tools und Integration

  • mypy: Statische Typüberprüfung
  • pylint: Code-Analyse mit Type-Hint-Support
  • IDE-Support: VS Code, PyCharm unterstützen Type Hints
  • pydantic: Runtime-Validation mit Type Hints

Fazit

Type Hints machen Python-Code:

  • Lesbarer und selbstdokumentierend
  • Weniger fehleranfällig
  • Einfacher zu warten
  • Kompatibel mit modernen Entwicklungstools

Sie sind optional, aber sehr empfehlenswert für professionelle Python-Entwicklung.

Zuletzt aktualisiert am