1. @dataclass: Die Fertighaus-Gussform 🏗️📦
In vielen Programmen dienen Klassen primär als Datenbehälter. Bisher musstest du dafür seitenweise denselben Standard-Code schreiben:
🔴 Klassisch (Viel Tipparbeit)
class Artikel: def __init__(self, name, preis): self.name = name self.preis = preis def __repr__(self): return f"Artikel({self.name}, {self.preis})" def __eq__(self, other): return (self.name, self.preis) == (other.name, other.preis)
🟢 Modern mit @dataclass
from dataclasses import dataclass, field @dataclass class Artikel: name: str preis: float kategorie: str = "Allgemein"
Schreibe in einer Dataclass niemals liste: list = [], da sonst alle Instanzen dieselbe Liste teilen! Nutze stattdessen immer field(default_factory=list).
2. Moderne Type Hints im Überblick 🏷️
Type Hints machen deinen Code selbsterklärend und ermöglichen IDEs wie VS Code blitzschnelle Autovervollständigung und Fehlerwarnungen:
| Type Hint | Bedeutung | Praxis-Beispiel |
|---|---|---|
Optional[str] |
Kann str oder None sein |
def suche(id: int) -> Optional[User]: ... |
Union[int, float] |
Zahl kann Ganzzahl oder Fließkomma sein | def runden(wert: Union[int, float]) -> float: ... |
Callable[[A, B], C] |
Eine übergebene Funktion | def ausfuehren(func: Callable) -> None: ... |
Dict[str, Any] |
Schlüssel sind Strings, Werte beliebig | user_config: Dict[str, Any] = {"theme": "dark"} |
3. Eigene Decorators schreiben: Das Geschenkverpackungs-Muster 🎁
Ein Decorator ist eine Funktion, die eine andere Funktion einpackt und ihr zusätzliche Fähigkeiten verleiht (z.B. Zeitmessung, Logging, Aufrufzählung):
import time import functools def zeitmessung(func): @functools.wraps(func) # Erhält Name und Docstring der Originalfunktion def wrapper(*args, **kwargs): start = time.perf_counter() ergebnis = func(*args, **kwargs) dauer = time.perf_counter() - start print(f"[⏱️] {func.__name__} brauchte {dauer:.6f}s") return ergebnis return wrapper @zeitmessung def schwere_berechnung(): return sum(x**2 for x in range(500_000))
4. 🎯 Deine Aufgaben in aufgabe.py
Öffne die Datei aufgabe.py und hake die Schritte nach und nach ab:
💡 Lösungshinweise (Aufklappen bei Bedarf)
🔍 Tipp zu TODO 8: Aufruf-Zähler als Decorator
Initialisiere das Attribut am Wrapper vor der Rückgabe:
def aufruf_zaehler(func): @functools.wraps(func) def wrapper(*args, **kwargs): wrapper.aufrufe += 1 return func(*args, **kwargs) wrapper.aufrufe = 0 return wrapper
🔍 Tipp zu TODO 3: @classmethod als Fabrikmethode
cls ist die Klasse selbst. Teile den String und rufe cls(...) auf:
@classmethod def aus_csv_zeile(cls, csv_zeile: str) -> "Artikel": teile = [t.strip() for t in csv_zeile.split(";")] return cls(name=teile[0], preis=float(teile[1]), kategorie=teile[2] if len(teile) > 2 else "Allgemein")
5. 🧪 Lösung überprüfen & Testen
1. Automatische Tests ausführen:
python3 test_aufgabe.py
2. Interaktives Skript starten:
python3 aufgabe.py