- Dynamic Sidebar mit window.COURSES_MANIFEST für 13 Kurse (216 Kapitel) - Kurswechsler Dropdown mit Direktnavigation - Fortschrittsanzeige mit Solved-Checkmarks (✓) aus localStorage - Responsive Off-Canvas Drawer mit Floating Action Button (☰ Kapitel) & Backdrop auf Mobile/Tablets - Web-IDE Topbar Drawer-Button (☰ Kapitel) für unterbrechungsfreien Vollbild-Editor - Saubere Bereinigung redundanter statischer Legacy-Sidebars |
||
|---|---|---|
| .. | ||
| aufgabe.py | ||
| index.html | ||
| musterloesung.py | ||
| README.md | ||
| test_aufgabe.py | ||
Kapitel 15: Parameter (*args, **kwargs) & Eigene Container 🎒📦
Willkommen zu Kapitel 15! In diesem Modul meisterst du zwei der mächtigsten und flexibelsten Sprachfeatures von Python:
- Variable Parameterlisten (
*argsund**kwargs) sowie Argument-Unpacking (*liste,**dict). - Eigene Container-Klassen, die sich dank magischer Dunder-Methoden genau wie Pythons eingebaute Listen und Dictionaries verhalten (
len(),[],del,in,for).
🧭 Didaktischer Hintergrund (Schulabgleich 29.0 & 30.0)
In der professionellen Softwareentwicklung und im Lehrplan sind flexible Schnittstellen und eigene Datenstrukturen essenziell:
- Schulabgleich 29.0: Variable Parameterlisten (
*args,**kwargs) und Argument-Unpacking. - Schulabgleich 30.0: Eigene Sequenzen und Container-Klassen mit dem Python-Container-Protokoll (
__len__,__getitem__,__setitem__,__delitem__,__contains__,__iter__).
🧰 1. Variable Parameterlisten: *args und **kwargs
Normalerweise hat eine Python-Funktion eine feste Anzahl von Parametern:
def addiere_zwei(a: float, b: float) -> float:
return a + b
Was aber, wenn du eine Funktion schreiben möchtest, die 2, 5 oder 100 Zahlen zusammenrechnet? Oder eine Funktion, die beliebige Spieler-Attribute entgegennimmt?
A) *args (Beliebig viele Positionsargumente als Tupel)
Das Sternchen * vor einem Parameternamen signalisiert Python: „Sammle alle überschüssigen Positionsargumente in einem unveränderlichen Tupel!“
def berechne_summe(*zahlen: float) -> float:
print(type(zahlen)) # <class 'tuple'>
return sum(zahlen)
print(berechne_summe(10, 20)) # -> 30 (zahlen ist (10, 20))
print(berechne_summe(1, 2, 3, 4, 5)) # -> 15 (zahlen ist (1, 2, 3, 4, 5))
print(berechne_summe()) # -> 0 (zahlen ist ())
💡 Analogie:
*argsist wie ein unendlicher Werkzeuggürtel. Egal ob du 1 Schraubendreher oder 10 Hämmer hineinsteckst – alle werden gebündelt in ein Tupel gelegt.
B) **kwargs (Beliebig viele Schlüsselwortargumente als Dict)
Zwei Sternchen ** signalisieren Python: „Sammle alle benannten Argumente (schluessel=wert) in einem Dictionary!“
def erstelle_held(name: str, **attribute) -> dict:
print(type(attribute)) # <class 'dict'>
return {"name": name, **attribute}
held = erstelle_held("Legolas", klasse="Waldlaeufer", level=15, waffe="Elbenbogen")
# -> {'name': 'Legolas', 'klasse': 'Waldlaeufer', 'level': 15, 'waffe': 'Elbenbogen'}
💡 Analogie:
**kwargsist wie ein ausfüllbares Formular. Der Aufrufer kann beliebig viele zusätzliche Zeilen mit Label und Wert ergänzen.
C) Die goldene Reihenfolge bei Parametern
Wenn du normale Parameter, *args, Default-Werte und **kwargs kombinierst, gilt stets diese feste Reihenfolge:
def super_funktion(pos1, pos2, *args, standard_wert=10, **kwargs):
pass
- Positionsargumente (
pos1,pos2) *args(Restliche Positionsargumente)- Keyword-Only / Default-Parameter (
standard_wert=10) **kwargs(Restliche Keyword-Argumente)
🎁 2. Argument-Unpacking: *liste und **dict
Der Stern-Operator funktioniert nicht nur bei der Definition von Funktionen (Packen), sondern auch beim Aufruf (Entpacken / Unpacking):
# 1. Listen-Unpacking mit *
preise = [19.99, 49.99, 9.99]
# Statt berechne_summe(preise[0], preise[1], preise[2]):
gesamt = berechne_summe(*preise)
# 2. Dictionary-Unpacking mit **
config = {"klasse": "Magier", "level": 20, "element": "Feuer"}
# Statt erstelle_held("Merlin", klasse="Magier", level=20, element="Feuer"):
magier = erstelle_held("Merlin", **config)
🎒 3. Eigene Container-Klassen mit Dunder-Methoden
Warum fühlt sich Python so elegant an? Weil eingebaute Typen (list, dict) und eigene Klassen exakt dieselben Operatoren nutzen können!
Wenn du eine Klasse Inventar erstellst, möchtest du:
len(inventar)stattinventar.get_anzahl()inventar[0]oderinventar["Schwert"]stattinventar.get_element(0)inventar[0] = trankstattinventar.set_element(0, trank)del inventar["Schwert"]stattinventar.remove_element("Schwert")'Heiltrank' in inventarstattinventar.enthaelt("Heiltrank")for item in inventar:statt umständlicher Index-Schleifen
Die magischen Container-Dunder im Überblick:
| Dunder-Methode | Ausgelöst durch | Zweck |
|---|---|---|
__len__(self) |
len(container) |
Gibt die Anzahl der Elemente als int zurück. |
__getitem__(self, key) |
container[key] |
Liest Element an Index key (z.B. int 0 oder str "Schwert"). |
__setitem__(self, key, val) |
container[key] = val |
Setzt/Ersetzt Element an Index key. |
__delitem__(self, key) |
del container[key] |
Löscht das Element an Index key. |
__contains__(self, item) |
item in container |
Gibt True zurück, wenn item enthalten ist, sonst False. |
__iter__(self) |
for x in container: |
Gibt einen Iterator zurück (iter(self._items)). |
🎮 4. Praxisbeispiel: Das Gaming-Inventar
In aufgabe.py baust du das RPG-Inventar eines Helden:
┌────────────────────────────────────────────────────────┐
│ 🎒 Inventar (Maximalgewicht: 20.0 kg) │
│ ├── [0] Eisenschwert (3.5 kg, 120 G) │
│ ├── [1] Holzschild (2.0 kg, 45 G) │
│ └── [2] Heiltrank (0.5 kg, 20 G) │
│ ───────────────────────────────────────────────── │
│ Gesamtgewicht: 6.0 / 20.0 kg (Frei: 14.0 kg) │
│ len(inv) -> 3 │
│ "Eisenschwert" in inv -> True │
│ inv["Heiltrank"] -> Gegenstand('Heiltrank', ...) │
└────────────────────────────────────────────────────────┘
📁 Die Dateien in diesem Ordner
index.html: Interaktive Web-Lernseite mit visuellen Tabellen, Rucksack-Analogie, Cheat-Sheets und Checkliste.aufgabe.py: Dein Arbeitsblatt mit Type Hints und TODOs für*args,**kwargsund die KlasseInventar.test_aufgabe.py: Automatische Unittest-Suite zur Überprüfung aller Anforderungen.musterloesung.py: Vollständig ausprogrammierte Referenzlösung.
🚀 Schnellstart
# 1. Bearbeite aufgabe.py
# 2. Führe die automatischen Tests aus:
python3 test_aufgabe.py
# 3. Oder starte aufgabe.py direkt:
python3 aufgabe.py