1. Warum flexible Parameter & eigene Container?
In einfachen Programmen hat jede Funktion eine starre Anzahl von Parametern (z.B. def addiere(a, b)).
In realen Software-Projekten möchten wir jedoch oft:
- Funktionen aufrufen, die beliebig viele Argumente annehmen (wie
print()odermax()). - Optionale Konfigurationen und Attribute flexibel übergeben (wie bei Profilen oder Einstellungen).
- Eigene Klassen bauen, die sich wie Listen oder Dictionaries anfühlen (mit
len(),[index],inundfor-Schleifen).
*args(Der Werkzeuggürtel): Du packst beliebig viele Werkzeuge hinein. Python schnürt sie automatisch zu einem unveränderlichen Tupel zusammen.**kwargs(Das Etiketten-Fach): Du übergibst Dinge mit Beschriftung (z.B.schluessel=wert). Python bündelt sie zu einem Dictionary.- Container-Klasse (Der smarte Rucksack): Dein Rucksack weiß, wie schwer er maximal sein darf, wie viele Gegenstände hineinpassen (
len()), lässt dich per Griff hineinfassen ([0]oder["Schwert"]) und prüft, ob Proviant eingepackt ist (in).
2. Cheat-Sheet: *args, **kwargs & Unpacking
Python unterscheidet zwischen dem Packen (in der Funktionsdefinition) und dem Entpacken (beim Funktionsaufruf):
| Syntax | Typ in Python | Bedeutung & Verwendung | Code-Beispiel |
|---|---|---|---|
*args |
tuple |
Nimmt beliebig viele Positionsargumente entgegen. | def f(*zahlen): return sum(zahlen) |
**kwargs |
dict |
Nimmt beliebige Schlüsselwortargumente (k=v) entgegen. |
def f(**opt): return opt.get("lang", "de") |
*liste |
Unpacking | Entpackt Elemente einer Liste/Sequenz als einzelne Argumente. | werte = [10, 20]; f(*werte) |
**dict |
Unpacking | Entpackt Dictionary-Paare als benannte Schlüsselwortargumente. | daten = {"alter": 25}; f(**daten) |
def meine_funktion(pos1, pos2, *args, standard_option=True, **kwargs):
- Feste Positionsargumente (
pos1,pos2) - Variable Positionsargumente (
*args) - Optionale Argumente mit Default-Werten / Keyword-Only (
standard_option=True) - Variable Keyword-Argumente (
**kwargs)
3. Das Python Container-Protokoll: Magische Dunder-Methoden
Damit sich eine eigene Klasse wie ein nativer Python-Container verhält, überschreiben wir die speziellen Double-Underscore (Dunder) Methoden:
| Dunder-Methode | Auslöser (Python-Syntax) | Rückgabe / Verhalten | Fehler bei Ungültigkeit |
|---|---|---|---|
__len__(self) |
len(container) |
Gibt die Anzahl der Elemente als int >= 0 zurück. |
TypeError bei nicht-int |
__getitem__(self, key) |
container[key] |
Liest Element an Index key (z.B. int oder str-Name). |
IndexError / KeyError |
__setitem__(self, key, val) |
container[key] = val |
Ersetzt oder setzt das Element an Position key. |
IndexError / ValueError |
__delitem__(self, key) |
del container[key] |
Entfernt das Element an Position oder mit Name key. |
IndexError / KeyError |
__contains__(self, item) |
item in container |
Gibt True zurück, wenn Element existiert, sonst False. |
- |
__iter__(self) |
for x in container: |
Gibt einen Iterator zurück (z.B. iter(self._items)). |
- |
4. Das Gaming-Inventar im Detail
In dieser Übung implementierst du ein vollwertiges Rollenspiel-Inventar:
inv["Heiltrank"] → Findet Trank per Namen!•
"Holzschild" in inv → True•
inv.hinzufuegen(*items) → Prüft Maximalgewicht automatisch!
5. 📋 Deine Aufgaben-Checkliste
Öffne die Datei aufgabe.py und hake die Schritte nach und nach ab:
💡 Lösungshinweise (Aufklappen bei Bedarf)
🔍 Tipp zu TODO 8: __getitem__ mit int und str unterstützen
Prüfe mit isinstance(), welcher Suchtyp übergeben wurde:
def __getitem__(self, key): if isinstance(key, int): return self._items[key] # Wirft automatisch IndexError bei ungültigem Index elif isinstance(key, str): for g in self._items: if g.name.lower() == key.lower(): return g raise KeyError(f"Gegenstand '{key}' nicht im Inventar gefunden!") else: raise TypeError("Index muss int oder str sein!")
🔍 Tipp zu TODO 9: Gewichtsberechnung bei __setitem__
Beim Ersetzen eines Elements musst du das Gewicht des alten Elements abziehen und das neue hinzurechnen:
altes_gewicht = self._items[index].gewicht neues_gesamtgewicht = self.gesamtgewicht - altes_gewicht + value.gewicht if neues_gesamtgewicht > self.max_gewicht: raise ValueError("Austausch überschreitet Maximalgewicht!") self._items[index] = value
6. 🧪 Lösung überprüfen & Testen
1. Automatische Tests ausführen:
python3 test_aufgabe.py
2. Interaktives Terminal-Skript starten:
python3 aufgabe.py
🧠 Diagnostischer Selbst-Check
Überprüfe dein Verständnis der Kernkonzepte und typischen Denkfallen, bevor du den Code in der Web-IDE schreibst.