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 15_parameter_und_container/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
+