1. Die wichtigste Idee: Bauplan vs. Haus
+1. Die Grundidee: Bauplan vs. Echtes Objekt
- In Python ist alles, was du bisher kennengelernt hast (Zahlen, Strings, Listen, Dictionaries), im Grunde ein Objekt. Doch jetzt lernst du, wie du deine ganz eigenen Datentypen erfindest! + In Python ist fast alles ein Objekt (Zahlen, Texte, Listen). Mit Klassen lernst du jetzt das mächtigste Werkzeug der Programmierung kennen: Deine eigenen Baupläne zu entwerfen!
Stell dir das Backen vor:
--
-
- Die Klasse (
class) ist die Ausstechform. Sie legt fest: Jedes Plätzchen hat einen Kopf, zwei Arme und zwei Beine. Die Form selbst kann man aber nicht essen.
- - Das Objekt (Instanz) ist das echte Plätzchen, das du aus dem Teig ausstichst. Ein Plätzchen bekommt Schokoglasur, das andere Zuckerstreusel. Beide stammen aus derselben Form, sind aber eigenständig! +
- Die Klasse (
class) ist die Ausstechform. Sie legt die Form fest (Kopf, Arme, Beine). Die Form selbst kann man nicht essen.
+ - Das Objekt (Instanz) ist das echte Plätzchen, das du aus dem Teig ausstichst. Ein Plätzchen bekommt Schokoglasur, ein anderes bunte Streusel. Beide stammen aus derselben Form, sind aber zwei völlig eigenständige Plätzchen!
Stell dir das Backen in der Küche vor:
+-
+
Warum nicht einfach Dictionaries?
-Ein Dictionary hat keine feste Struktur – man vertippt sich leicht:
- -tier1 = {"name": "Bello", "tierart": "Hund", "alter": 3} -tier2 = {"name": "Mimi", "art": "Katze", "alter": 5} # Ups! 'art' statt 'tierart'! -# Ein Programm würde hier abstürzen, weil tier2["tierart"] nicht existiert!-
Mit einer Klasse definierst du eine klare, wiederverwendbare Struktur.
2. Wie definiert und nutzt man eine Klasse?
- -Eine einfache Klasse erstellst du mit dem Schlüsselwort class:
2. Warum machen Klassen deinen Code besser?
+ +Schauen wir uns an, wie man Daten bisher mit Dictionaries gespeichert hat – und warum eine Klasse viel übersichtlicher und sicherer ist:
# 1. Bauplan definieren: -class Auto: - pass # pass bedeutet: Hier steht erst mal kein weiterer Code ++# Hund 1 mit Dictionary +hund1 = {"name": "Bello", "rasse": "Labrador", "alter": 3} -# 2. Ein Objekt erzeugen (Instanziierung): -mein_auto = Auto() +# Hund 2: Ups! Hier haben wir uns beim Schlüssel vertippt ("tier_rasse" statt "rasse")! +hund2 = {"name": "Luna", "tier_rasse": "Pudel", "alter": 2} -# 3. Eigenschaften (Attribute) mit dem Punkt (.) setzen: -mein_auto.farbe = "Rot" -mein_auto.marke = "VW" -mein_auto.ps = 110 +# Wenn wir jetzt die Rasse ausgeben wollen: +print(hund1["rasse"]) # Funktioniert -> "Labrador" +print(hund2["rasse"]) # 💥 KeyError: 'rasse' existiert nicht! Programm stürzt ab!+ -# 4. Werte wieder abfragen: -print(mein_auto.farbe) # Gibt "Rot" aus
Jetzt das Ganze mit einer Klasse:
+ +# 1. Wir definieren den gemeinsamen Bauplan: +class Hund: + pass + +# 2. Wir erstellen zwei konkrete Hunde (Instanzen): +bello = Hund() +bello.name = "Bello" +bello.rasse = "Labrador" +bello.alter = 3 + +luna = Hund() +luna.name = "Luna" +luna.rasse = "Pudel" +luna.alter = 2 + +# 3. Jetzt greifen wir mit der Punkt-Notation (.) auf die Eigenschaften zu: +print(bello.name, "ist ein", bello.rasse) # Ausgabe: Bello ist ein Labrador +print(luna.name, "ist ein", luna.rasse) # Ausgabe: Luna ist ein Pudel+
3. 🌟 Vollständiges Praxisbeispiel: Der Fahrrad-Verleih
+ +Hier siehst du ein vollständiges, funktionierendes Python-Skript von Anfang bis Ende. Schau dir genau an, wie Objekte erstellt, Eigenschaften zugewiesen und in Funktionen verwendet werden:
+ +# ============================================================================== +# SCHRITT 1: Die Klasse (der Bauplan) definieren +# ============================================================================== +class Fahrrad: + pass + + +# ============================================================================== +# SCHRITT 2: Eine Funktion, die Fahrräder beschreibt +# ============================================================================== +def fahrrad_info(bike): + # Wir greifen über den Punkt auf die Attribute des übergebenen Objekts zu: + return f"{bike.marke} ({bike.farbe}) - {bike.gaenge} Gänge - {bike.preis_pro_tag}€/Tag" + + +# ============================================================================== +# SCHRITT 3: Eine Funktion, die prüft, welches Fahrrad günstiger ist +# ============================================================================== +def guenstigeres_rad(rad_a, rad_b): + if rad_a.preis_pro_tag < rad_b.preis_pro_tag: + return rad_a + else: + return rad_b + + +# ============================================================================== +# SCHRITT 4: Wir erzeugen konkrete Objekte und probieren alles aus! +# ============================================================================== +if __name__ == "__main__": + # Erstes Fahrrad-Objekt erstellen: + mountainbike = Fahrrad() + mountainbike.marke = "Cube" + mountainbike.farbe = "Schwarz/Grün" + mountainbike.gaenge = 21 + mountainbike.preis_pro_tag = 25.0 + + # Zweites Fahrrad-Objekt erstellen: + citybike = Fahrrad() + citybike.marke = "Gazelle" + citybike.farbe = "Himmelblau" + citybike.gaenge = 7 + citybike.preis_pro_tag = 15.0 + + # Infos ausgeben: + print("Verfügbare Räder:") + print("1.", fahrrad_info(mountainbike)) + print("2.", fahrrad_info(citybike)) + + # Günstigeres Rad finden: + schnaeppchen = guenstigeres_rad(mountainbike, citybike) + print(f"\nDas günstigere Rad ist das {schnaeppchen.marke} für nur {schnaeppchen.preis_pro_tag}€!")+
mountainbike und citybike sind zwei getrennte Variablen im Arbeitsspeicher. Jedes hat seine eigenen Werte für .marke, .farbe und .preis_pro_tag, obwohl beide aus der Klasse Fahrrad stammen!
+ 4. ⚠️ Häufige Stolperfallen für Einsteiger
+ +mein_rad = Fahrrad() ✓ (Richtig: Erzeugt ein neues Objekt!)+
mein_rad = Fahrrad ✗ (Falsch: Speichert nur den Bauplan in die Variable!)
Haustier, BankKonto), während Variablen und Funktionen klein geschrieben werden (z.B. mein_haustier, erstelle_tier()).
+ Haustier, Fahrrad). Variablen und Funktionsnamen schreibt man klein (bello, erstelle_bello()).
+ erstelle_bello()), muss am Ende unbedingt return mein_tier stehen! Ohne return gibt Python automatisch None zurück.
3. Deine Aufgaben in aufgabe.py
+ 5. 🎯 Deine Aufgaben in aufgabe.py
- Öffne die Datei 01_einstieg_klassen/aufgabe.py und bearbeite die nummerierten TODOs:
Öffne die Datei 01_einstieg_klassen/aufgabe.py in deinem Editor und bearbeite die Aufgaben:
- @@ -113,66 +210,66 @@
💡 Lösungshinweise (Aufklappen bei Bedarf)
+💡 Lösungshinweise (Aufklappen, wenn du Hilfe brauchst)
Tipp zu TODO 1 & 2 (Objekt erstellen und befüllen)
+🔍 Tipp zu TODO 1 & 2 (Klasse & Objekt erstellen)
class Haustier: pass def erstelle_bello(): - tier = Haustier() # Neues Objekt erzeugen - tier.name = "Bello" + tier = Haustier() # 1. Neues Haustier-Objekt bauen + tier.name = "Bello" # 2. Attribute zuweisen tier.tierart = "Hund" tier.alter = 3 - return tier # WICHTIG: Das fertige Objekt zurückgeben!+ return tier # 3. Objekt zurückgeben!
Tipp zu TODO 5 (Tiere vergleichen)
+🔍 Tipp zu TODO 5 (Tiere vergleichen)
Du kannst mit einem einfachen if auf die Attribute der übergebenen Objekte zugreifen:
if tier2.alter > tier1.alter: - return tier2 -else: - return tier1+
def aelteres_tier(tier1, tier2): + if tier2.alter > tier1.alter: + return tier2 + else: + return tier1
4. Lösung überprüfen
-Führe im Terminal im Ordner 01_einstieg_klassen folgenden Befehl aus:
6. 🧪 Lösung überprüfen
+Öffne das Terminal und führe den Test aus:
Der Konstruktor __init__ & das geheimnisvolle self 💳
- Lerne, wie Objekte direkt beim Erstellen startklar gemacht werden und baue eine Taschengeld-Konto App.
+Lerne, wie Objekte direkt beim Erstellen startklar gemacht werden – mit vollständigen Codebeispielen.
1. Warum brauchen wir __init__?
- In Kapitel 01 mussten wir jedes Attribut mühsam von Hand setzen: + In Kapitel 01 mussten wir jedes Attribut mühsam nach dem Erstellen von Hand setzen:
bello = Haustier() bello.name = "Bello" -bello.alter = 3 # Was passiert, wenn man hier das Alter vergisst? -> Programm stürzt ab!+bello.alter = 3 # Wenn wir 100 Tiere haben, müssen wir hunderte Zeilen schreiben!
- Deshalb gibt es den Konstruktor __init__. Er wird von Python automatisch aufgerufen, sobald ein neues Objekt erstellt wird!
+ Die Lösung heißt Konstruktor: Die spezielle Methode __init__. Sie wird von Python automatisch aufgerufen, genau in dem Moment, in dem du ein Objekt erzeugst!
__init__ ist wie das Ausfüllen des Datenblattes bei der Geburt – danach ist das Objekt sofort einsatzbereit!
- 2. Was bedeutet self?
+ 2. 📱 Vollständiges Beispiel: Die Smartphone-Klasse
-
- Das Wörtchen self steht auf Deutsch für "ich selbst" bzw. "dieses konkrete Objekt hier".
-
Schau dir an, wie eine vollständige Klasse mit Konstruktor und Methoden in der Praxis aussieht:
class Bankkonto: - def __init__(self, inhaber, kontostand=0.0): - self.inhaber = inhaber # Speichere 'inhaber' im Attribut DIESES Objekts - self.kontostand = kontostand # Speichere 'kontostand' in MEINEM Speicher ++# 1. Die vollständige Klasse definieren: +class Smartphone: + # Der Konstruktor wird automatisch beim Erstellen aufgerufen: + def __init__(self, modell, speicher_gb, akku=100): + self.modell = modell # z.B. "iPhone 15" + self.speicher_gb = speicher_gb # z.B. 128 + self.akku = akku # Standardwert ist 100% -# Verwendung: -konto_anna = Bankkonto("Anna", 50.0) -konto_ben = Bankkonto("Ben") # Verwendet den Standardwert 0.0+ # Eine Methode, die den Akkustand verringert: + def benutzen(self, minuten): + verbrauch = minuten * 0.5 + if self.akku >= verbrauch: + self.akku -= verbrauch + return f"{self.modell}: {minuten} Min. genutzt. Akku: {self.akku:.0f}%" + else: + self.akku = 0 + return f"{self.modell}: Akku ist leer!" + + # Eine Methode zum Aufladen: + def aufladen(self): + self.akku = 100 + return f"{self.modell} ist wieder voll aufgeladen (100%)!" + + +# ============================================================================== +# Jetzt verwenden wir die Smartphone-Klasse: +# ============================================================================== +if __name__ == "__main__": + # Handy 1 erstellen (nutzt Standard-Akku 100%): + mein_handy = Smartphone("iPhone 15", 256) + + # Handy 2 erstellen (mit 40% Start-Akku): + altes_handy = Smartphone("Galaxy S10", 64, akku=40) + + print(mein_handy.benutzen(30)) # Verbraucht 15% -> 85% Rest + print(altes_handy.benutzen(90)) # Akku wird leer! + print(altes_handy.aufladen()) # Wieder 100%
3. Was bedeutet self ganz genau?
+
+
+ Das Wörtchen self steht für "dieses konkrete Objekt hier".
+
mein_handy.benutzen(30) aufrufst, übergibt Python im Hintergrund automatisch mein_handy als erstes Argument self.
+ +
self.akku -= verbrauch bedeutet: "Ziehe den Verbrauch vom Akku DIESES Handys ab – nicht von allen anderen Handys auf der Welt!"
self.inhaber = inhaber?self.inhaber – das ist die Variable, die am Objekt dauerhaft gespeichert bleibt. Rechts steht inhaber – das ist nur der temporäre Übergabeparameter der Funktion.
+ -
+
- Links (
self.inhaber): Das Attribut, das fest am Objekt im Arbeitsspeicher abgespeichert wird.
+ - Rechts (
inhaber): Der Wert, den jemand beim Aufruf in die Klammern übergeben hat.
+
3. Häufige Stolperfallen beim Konstruktor
+4. ⚠️ Häufige Fehler beim Konstruktor
__init__ mit zwei Unterstrichen davor und danach (Dunder), NICHT _init_! Wenn du nur einen Unterstrich schreibst, ignoriert Python die Methode einfach.
+ def __init__(self): ✓ (2 Unterstriche vorne, 2 hinten: Dunder!)+
def _init_(self): ✗ (Falsch! Python ruft die Methode nicht auf!)
self im Methodenkopf vergessenself haben:
- def einzahlen(self, betrag): ✓
- def einzahlen(betrag): ✗ (Führt zu TypeError!)
+ def einzahlen(self, betrag): ✓+
def einzahlen(betrag): ✗ (Führt zu TypeError: takes 1 positional argument but 2 were given)
+ self.kontostand = kontostand ✓+
kontostand = self.kontostand ✗ (Überschreibt den Parameter, speichert nichts am Objekt!)
4. Deine Aufgaben in aufgabe.py
+ 5. 🎯 Deine Aufgaben in aufgabe.py
Öffne die Datei 02_init_und_self/aufgabe.py:
💡 Lösungshinweise (Aufklappen bei Bedarf)
Tipp zu TODO 3 (Auszahlen mit Absicherung)
+🔍 Tipp zu TODO 3 (Auszahlen mit Absicherung)
def auszahlen(self, betrag): @@ -148,9 +195,9 @@ - +- 5. Lösung überprüfen
+6. 🧪 Lösung überprüfen
Führe im Terminal im Ordner
02_init_und_selffolgenden Befehl aus:diff --git a/03_methoden_und_verhalten/README.md b/03_methoden_und_verhalten/README.md index 2883b3f..8be3140 100644 --- a/03_methoden_und_verhalten/README.md +++ b/03_methoden_und_verhalten/README.md @@ -6,53 +6,50 @@ Funktionen, die innerhalb einer Klasse definiert sind, nennt man **Methoden**. --- -## 🏃♀️ Was unterscheidet eine Methode von einer normalen Funktion? - -1. Eine Methode steht **eingerückt in der Klasse**. -2. Das **erste Argument ist immer `self`**. -3. Über `self` hat die Methode direkten Zugriff auf alle Eigenschaften des Objekts und kann diese verändern. +## 🏎️ Vollständiges Praxisbeispiel: Die Rennauto-Klasse ```python -class Zauberer: - def __init__(self, name, mana=50): - self.name = name - self.mana = mana +class Rennauto: + def __init__(self, fahrer, speed, tank=50): + self.fahrer = fahrer + self.speed = speed # z.B. 220 km/h + self.tank = tank # Aktueller Tank in Litern + self.max_tank = tank # Maximales Tankvolumen + self.gefahrene_km = 0 - # Das hier ist eine Methode: - def zauberspruch_wirken(self, mana_kosten): - if self.mana >= mana_kosten: - self.mana -= mana_kosten - print(f"{self.name} wirkt einen Zauber! Verbleibendes Mana: {self.mana}") - return True + def fahren(self, km): + verbrauch = km * 0.2 + if self.tank >= verbrauch: + self.tank -= verbrauch + self.gefahrene_km += km + return f"{self.fahrer} fährt {km} km (Tank: {self.tank:.1f}L übrig)" else: - print(f"{self.name} hat nicht genug Mana!") - return False + return f"{self.fahrer} hat nicht genug Sprit für {km} km!" -merlin = Zauberer("Merlin", 30) -merlin.zauberspruch_wirken(10) # self wird automatisch merlin! + def tanken(self, liter): + freier_platz = self.max_tank - self.tank + getankt = min(freier_platz, liter) + self.tank += getankt + return f"{self.fahrer} tankt {getankt:.1f} Liter nach" + + def duell_gegen(self, gegner_auto): + if self.speed > gegner_auto.speed: + return f"{self.fahrer} überholt {gegner_auto.fahrer}!" + else: + return f"{gegner_auto.fahrer} zieht an {self.fahrer} vorbei!" + +# Testen: +auto1 = Rennauto("Max", 240, 40) +auto2 = Rennauto("Lewis", 235, 50) +print(auto1.fahren(100)) +print(auto1.duell_gegen(auto2)) ``` --- ## 🤝 Wenn Objekte miteinander interagieren! -Das Spannendste an der objektorientierten Programmierung ist, wenn **ein Objekt mit einem anderen Objekt interagiert**. - -Du kannst ein ganzes Objekt als Parameter an die Methode eines anderen Objekts übergeben: - -```python -class Spieler: - def __init__(self, name, geld): - self.name = name - self.geld = geld - - def bezahle_an(self, empfaenger, betrag): - if self.geld >= betrag: - self.geld -= betrag - empfaenger.geld += betrag # Wir greifen direkt auf das andere Objekt zu! - return True - return False -``` +Du kannst ein ganzes Objekt als Parameter an die Methode eines anderen Objekts übergeben (wie bei `auto1.duell_gegen(auto2)` oder `ritter.angreifen(drache)`). --- @@ -68,10 +65,12 @@ class Spieler: ## 🎯 Deine Aufgabe: Das RPG-Duell -In `aufgabe.py` erstellst du eine Klasse `Held` für ein Rollenspiel: -- Ein Held hat `name`, `leben`, `max_leben` und `angriffskraft`. -- Ein Held kann Schaden erleiden (`schaden_erleiden`), geheilt werden (`heilen`) und einen anderen Helden angreifen (`angreifen(gegner)`). -- Du sorgst mit Bedingungen dafür, dass die Lebenspunkte nicht unter `0` fallen und nicht über `max_leben` steigen! +In `aufgabe.py` erstellst du die Klasse `Held`: +- `__init__(self, name, leben=100, angriffskraft=15)` +- `schaden_erleiden(self, schaden)` +- `heilen(self, heilung)` +- `angreifen(self, gegner)` +- `status_text(self)` ### Testen: ```bash diff --git a/03_methoden_und_verhalten/index.html b/03_methoden_und_verhalten/index.html index e501f41..dccdff5 100644 --- a/03_methoden_und_verhalten/index.html +++ b/03_methoden_und_verhalten/index.html @@ -19,20 +19,35 @@Kapitel 03Methoden & Verhalten: Wenn Objekte lebendig werden ⚔️
-Lass Objekte aktiv handeln und miteinander interagieren in einem rundenbasierten RPG-Heldenduell.
+Lass Objekte aktiv handeln und miteinander interagieren anhand eines vollständigen Rennspiel- & Duell-Beispiels.
- + + + + 1. Was sind Methoden?
- Bisher haben unsere Klassen vor allem Daten gespeichert. Aber in der objektorientierten Programmierung haben Objekte auch Verhalten. Funktionen, die zu einer Klasse gehören, nennt man Methoden. + Bisher haben unsere Klassen vor allem Daten gespeichert. Aber in der echten Programmierung haben Objekte auch Verhalten (sie können etwas tun). Funktionen, die innerhalb einer Klasse stehen, nennt man Methoden.
+++💡 Der Unterschied zwischen Funktion und Methode:++
+- Eine Funktion steht frei im Code:
+berechne_summe(a, b)- Eine Methode gehört zu einem Objekt und wird mit Punkt aufgerufen:
+mein_held.angreifen(gegner)+ - +2. 🏎️ Vollständiges Beispiel: Die Rennauto-Klasse
+ +Hier siehst du eine vollständige Klasse mit Konstruktor, mehreren Methoden, Wertebegrenzung (Tankinhalt) und einer Renn-Simulation:
+-@@ -40,44 +55,76 @@- Python + Python (Komplettes Beispiel: rennauto.py)class Zauberer: - def __init__(self, name, mana=50): - self.name = name - self.mana = mana +class Rennauto: + def __init__(self, fahrer, speed, tank=50): + self.fahrer = fahrer + self.speed = speed # z.B. 220 km/h + self.tank = tank # Aktueller Tank in Litern + self.max_tank = tank # Maximales Tankvolumen + self.gefahrene_km = 0 - # Eine Methode gehört dem Zauberer: - def zauberspruch_wirken(self, kosten): - if self.mana >= kosten: - self.mana -= kosten - return True - return False+ # Methode 1: Fahren (verbraucht Benzin) + def fahren(self, km): + verbrauch = km * 0.2 # 0.2 Liter pro km + if self.tank >= verbrauch: + self.tank -= verbrauch + self.gefahrene_km += km + return f"{self.fahrer} fährt {km} km (Tank: {self.tank:.1f}L übrig)" + else: + return f"{self.fahrer} hat nicht genug Sprit für {km} km!" + + # Methode 2: Tanken (nicht über max_tank) + def tanken(self, liter): + freier_platz = self.max_tank - self.tank + getankt = min(freier_platz, liter) + self.tank += getankt + return f"{self.fahrer} tankt {getankt:.1f} Liter nach (Tank: {self.tank:.1f}/{self.max_tank}L)" + + # Methode 3: Interaktion mit einem anderen Auto + def duell_gegen(self, gegner_auto): + if self.speed > gegner_auto.speed: + return f"{self.fahrer} überholt {gegner_auto.fahrer} mit Leichtigkeit!" + elif self.speed < gegner_auto.speed: + return f"{gegner_auto.fahrer} zieht an {self.fahrer} vorbei!" + else: + return f"{self.fahrer} und {gegner_auto.fahrer} sind genau gleich schnell!" + + +# Ausprobieren: +if __name__ == "__main__": + auto1 = Rennauto("Max", speed=240, tank=40) + auto2 = Rennauto("Lewis", speed=235, tank=50) + + print(auto1.fahren(100)) # Verbraucht 20 Liter -> 20L übrig + print(auto1.duell_gegen(auto2)) # Max ist schneller als Lewis! + print(auto1.tanken(30)) # Tankt bis max 40L auf- - +2. Wenn zwei Objekte miteinander interagieren
+3. 🤝 Interaktion: Ein Objekt übergibt sich an ein anderes
- Besonders spannend wird es, wenn eine Methode eines Objekts ein anderes Objekt als Parameter bekommt (z.B.
ritter.angreifen(drache)). + In der Methodeangreifen(self, gegner)übergibst du das gegnerische Held-Objekt als Parameter:-- -🤝 Die Duell-Analogie:- Inangreifen(self, gegner)istselfder Angreifer (z.B. Arthur) undgegnerist das Ziel (z.B. der Drache). Arthur ruftgegner.schaden_erleiden(self.angriffskraft)auf. So beeinflussen sich die Objekte gegenseitig! --⚠️ Wichtig: Logische Grenzen einhalten (Clamping)!- Lebenspunkte dürfen niemals unter0fallen (ein besiegter Held hat 0 HP, nicht -15 HP) und bei Heilung niemals übermax_lebensteigen. +⚔️ Wie das Helden-Duell funktioniert:+ritter.angreifen(drache)+
+ 1.selfist der Ritter (mitself.angriffskraft).
+ 2.gegnerist der Drache.
+ 3. Der Ritter ruft:gegner.schaden_erleiden(self.angriffskraft)auf!
+ 4. Der Drache verliert Leben und prüft, ob er noch lebt.- - +3. Deine Aufgaben in
+aufgabe.py4. 🎯 Deine Aufgaben in
aufgabe.py@@ -115,23 +162,22 @@
- @@ -89,25 +136,25 @@
💡 Lösungshinweise (Aufklappen bei Bedarf)
-Tipp zu TODO 3 (Heilung begrenzen)
+🔍 Tipp zu TODO 4 (Angriff)
-def heilen(self, heilung): - if not self.ist_am_leben or heilung <= 0: - return 0 - alter_wert = self.leben - self.leben = min(self.max_leben, self.leben + heilung) - return self.leben - alter_wert # Wie viel wurde wirklich geheilt?+def angreifen(self, gegner): + if self.ist_am_leben and gegner.ist_am_leben: + gegner.schaden_erleiden(self.angriffskraft) + return True + return False- - +4. Lösung überprüfen
+5. 🧪 Lösung überprüfen
Führe im Terminal im Ordner
03_methoden_und_verhaltenfolgenden Befehl aus:diff --git a/04_str_und_darstellung/README.md b/04_str_und_darstellung/README.md index 1e4026d..a78f169 100644 --- a/04_str_und_darstellung/README.md +++ b/04_str_und_darstellung/README.md @@ -19,43 +19,46 @@ Das ist kryptisch und hilft im Alltag nicht weiter. Aber Python hat dafür eine --- -## ✨ Die `__str__`-Methode - -Wann immer Python ein Objekt in einen Text umwandeln soll (z.B. bei `print(mein_objekt)` oder `str(mein_objekt)` oder in einem f-String `f"Das Buch: {mein_objekt}"`), schaut Python nach, ob deine Klasse eine `__str__`-Methode hat. - -Wenn ja, ruft Python sie automatisch auf: +## 🍕 Vollständiges Praxisbeispiel: Pizza & Pizzeria-Bestellung ```python -class Buch: - def __init__(self, titel, autor): - self.titel = titel - self.autor = autor +# 1. Klasse Pizza mit __str__: +class Pizza: + def __init__(self, name, preis, extra_kaese=False): + self.name = name + self.preis = preis + self.extra_kaese = extra_kaese + if extra_kaese: + self.preis += 1.50 def __str__(self): - # Muss immer einen STRING zurückgeben (return)! - return f"'{self.titel}' von {self.autor}" + kaese = " (mit Extra-Käse)" if self.extra_kaese else "" + return f"Pizza {self.name}{kaese} - {self.preis:.2f} €" -mein_buch = Buch("Harry Potter", "J.K. Rowling") -print(mein_buch) # Ausgabe: 'Harry Potter' von J.K. Rowling 🎉 -``` +# 2. Klasse Bestellung verwaltet Pizza-Objekte: +class Bestellung: + def __init__(self, kunden_name): + self.kunden_name = kunden_name + self.pizzen = [] ---- + def pizza_hinzufuegen(self, pizza): + self.pizzen.append(pizza) -## 🧺 Objekte in Listen verwalten + def gesamtpreis(self): + return sum(p.preis for p in self.pizzen) -Oft hat man Objekte, die eine Liste von *anderen* Objekten verwalten (z.B. ein Warenkorb, der Artikel enthält, oder ein Bus, der Fahrgäste enthält): + def rechnung_drucken(self): + zeilen = [f"=== RECHNUNG FÜR {self.kunden_name} ==="] + for p in self.pizzen: + zeilen.append(f"- {p}") # Ruft p.__str__() auf! + zeilen.append(f"Gesamt: {self.gesamtpreis():.2f} €") + return "\n".join(zeilen) -```python -class Schultasche: - def __init__(self): - self.buecher = [] # Startet mit einer leeren Liste - - def buch_einpacken(self, buch): - self.buecher.append(buch) - - def inhalt_anzeigen(self): - for b in self.buecher: - print(f"- {b}") # Hier wird automatisch b.__str__() genutzt! +# Testen: +bestellung = Bestellung("Lisa") +bestellung.pizza_hinzufuegen(Pizza("Margherita", 8.50)) +bestellung.pizza_hinzufuegen(Pizza("Salami", 9.50, extra_kaese=True)) +print(bestellung.rechnung_drucken()) ``` --- diff --git a/04_str_und_darstellung/index.html b/04_str_und_darstellung/index.html index 6fae5f0..0e558d5 100644 --- a/04_str_und_darstellung/index.html +++ b/04_str_und_darstellung/index.html @@ -19,18 +19,18 @@Kapitel 04Schöne Ausgaben mit
-__str__& Objektlisten 🧾Lerne, wie du bestimmst, was beim
+print(objekt)erscheint und wie Objekte andere Objekte in Listen verwalten.Lerne anhand eines Pizzeria-Beispiels, wie du
print(objekt)formatierst und Objekte in Listen sammelst.- + - + + +1. Warum sieht
+print(objekt)standardmäßig so hässlich aus?1. Warum sieht
print(objekt)standardmäßig so kryptisch aus?- Wenn du versuchst, ein Objekt ohne Dunder-Methode zu drucken: + Wenn du versuchst, ein Objekt ohne die Dunder-Methode
__str__auszudrucken:@@ -39,13 +39,20 @@- Python weiß ohne deine Hilfe nicht, wie du dein Objekt darstellen möchtest. + Python weiß nicht, welche Attribute für einen Menschen interessant sind.
+✨ Die Magie von- Sobald du in deiner Klasse eine Methode__str__:def __str__(self):definierst, ruft Python diese automatisch auf, wann immer das Objekt zu Text umgewandelt wird (beiprint(),str()oder in f-Strings)! + Sobald du in deiner Klasse die Methodedef __str__(self):definierst, ruft Python diese automatisch auf, sobald das Objekt in Text umgewandelt werden soll (beiprint(),str()oder in f-Stringsf"{objekt}")!+ 2. 🍕 Vollständiges Beispiel: Pizza & Pizzeria-Bestellung
+ +Hier siehst du zwei vollständige Klassen, die zusammenarbeiten:
Pizza(mit__str__) undBestellung(die eine Liste von Pizzen verwaltet):-@@ -54,38 +61,81 @@- Python + Python (Komplettes Beispiel: pizzeria.py)class Buch: - def __init__(self, titel, autor): - self.titel = titel - self.autor = autor +# ============================================================================== +# KLASSE 1: Einzelne Pizza mit schöner __str__ Ausgabe +# ============================================================================== +class Pizza: + def __init__(self, name, preis, extra_kaese=False): + self.name = name + self.preis = preis + self.extra_kaese = extra_kaese + if extra_kaese: + self.preis += 1.50 # Extra Käse kostet 1.50€ mehr + # Diese Methode bestimmt, wie die Pizza als Text aussieht: def __str__(self): - return f"'{self.titel}' von {self.autor}" # MUSS ein String sein! + kaese_hinweis = " (mit Extra-Käse 🧀)" if self.extra_kaese else "" + return f"Pizza {self.name}{kaese_hinweis} - {self.preis:.2f} €" -mein_buch = Buch("Harry Potter", "J.K. Rowling") -print(mein_buch) # Ausgabe: 'Harry Potter' von J.K. Rowling+ +# ============================================================================== +# KLASSE 2: Bestellung verwaltet eine Liste von Pizzen +# ============================================================================== +class Bestellung: + def __init__(self, kunden_name): + self.kunden_name = kunden_name + self.pizzen = [] # Startet mit einer leeren Liste + + def pizza_hinzufuegen(self, pizza): + self.pizzen.append(pizza) + + def gesamtpreis(self): + return sum(p.preis for p in self.pizzen) + + def rechnung_drucken(self): + zeilen = [f"=== RECHNUNG FÜR {self.kunden_name.upper()} ==="] + for p in self.pizzen: + zeilen.append(f"- {p}") # Hier wird automatisch p.__str__() aufgerufen! + zeilen.append("--------------------------------") + zeilen.append(f"Gesamtsumme: {self.gesamtpreis():.2f} €") + return "\n".join(zeilen) + + +# Ausprobieren: +if __name__ == "__main__": + bestellung = Bestellung("Lisa") + + p1 = Pizza("Margherita", 8.50) + p2 = Pizza("Salami", 9.50, extra_kaese=True) + + bestellung.pizza_hinzufuegen(p1) + bestellung.pizza_hinzufuegen(p2) + + print(bestellung.rechnung_drucken())- 2. Objekte in Listen verwalten
+3. ⚠️ Wichtig bei
-__str__- Eine Klasse kann als Attribut eine Liste von anderen Objekten haben: -
++-1. Immer 'return', niemals 'print'!+def __str__(self): return f"..."✓
+def __str__(self): print(f"...")✗ (Falsch!__str__MUSS einen String mitreturnzurückgeben!) +-🛒 Der Warenkorb:- EinWarenkorbbesitzt eine Listeself.artikel_liste = []. Wenn du einenArtikelhinzufügst, landet das ganze Artikel-Objekt in der Liste! ++- +2. Rückgabewert muss zwingend ein String sein:+ Wenn du eine Zahl zurückgibst (z.B.return self.preis), stürzt Python ab mitTypeError: __str__ returned non-string. Nutze immer f-Stringsf"{self.preis}"oderstr(...).- 3. Deine Aufgaben in
+aufgabe.py4. 🎯 Deine Aufgaben in
aufgabe.py
- @@ -103,7 +153,7 @@
- @@ -117,7 +167,7 @@
💡 Lösungshinweise (Aufklappen bei Bedarf)
-Tipp zu TODO 7 (Kassenzettel zusammensetzen)
+🔍 Tipp zu TODO 7 (Kassenzettel zusammensetzen)
def bon_text(self): @@ -132,9 +182,9 @@ - +- 4. Lösung überprüfen
+5. 🧪 Lösung überprüfen
Führe im Terminal im Ordner
04_str_und_darstellungfolgenden Befehl aus:diff --git a/05_objekte_kombinieren/README.md b/05_objekte_kombinieren/README.md index a5d4b46..4e626ec 100644 --- a/05_objekte_kombinieren/README.md +++ b/05_objekte_kombinieren/README.md @@ -4,66 +4,62 @@ In der echten Softwareentwicklung (wie bei Spotify, Instagram oder Netflix) best Wenn eine Klasse andere Objekte besitzt oder verwaltet, nennt man das **Komposition** (oder *"hat-ein"-Beziehung*): - Eine **Playlist** *hat viele* **Songs**. +- Eine **Schulklasse** *hat viele* **Schüler**. - Ein **Kino** *hat viele* **Säle** und **Filme**. -- Eine **Schule** *hat viele* **Klassen** und **Schüler**. --- -## 🎶 Das Zusammenspiel: Song & Playlist - -Schauen wir uns an, wie eine Playlist mit Songs arbeiten kann: +## 🎒 Vollständiges Praxisbeispiel: Der Schüler- & Notenmanager ```python -class Song: - def __init__(self, titel, dauer_sekunden): - self.titel = titel - self.dauer_sekunden = dauer_sekunden - -class Playlist: - def __init__(self, name): +# 1. Klasse Schueler +class Schueler: + def __init__(self, name, note): self.name = name - self.songs = [] # Hier landen die Song-Objekte + self.note = float(note) - def hinzufuegen(self, song): - self.songs.append(song) + def __str__(self): + return f"{self.name} (Note: {self.note:.1f})" - def finde_lange_songs(self, min_sekunden): - gefundene = [] - for song in self.songs: - if song.dauer_sekunden >= min_sekunden: - gefundene.append(song) - return gefundene +# 2. Klasse Schulklasse verwaltet viele Schüler-Objekte: +class Schulklasse: + def __init__(self, klassen_name): + self.klassen_name = klassen_name + self.schueler_liste = [] + + def hinzufuegen(self, schueler): + self.schueler_liste.append(schueler) + + def notendurchschnitt(self): + if not self.schueler_liste: + return 0.0 + summe = sum(s.note for s in self.schueler_liste) + return summe / len(self.schueler_liste) + +# Testen: +klasse_9a = Schulklasse("Klasse 9a") +klasse_9a.hinzufuegen(Schueler("Emma", 1.0)) +klasse_9a.hinzufuegen(Schueler("Lukas", 2.3)) +klasse_9a.hinzufuegen(Schueler("Mia", 1.3)) + +print("Durchschnitt:", klasse_9a.notendurchschnitt()) ``` --- ## ⏱️ Zeit-Formatierung: Aus Sekunden werden Minuten & Sekunden -Um z.B. `215` Sekunden als `"03:35"` darzustellen, teilt man mit Ganzzahldivision `//` und Modulo `%`: ```python -sekunden_gesamt = 215 -minuten = sekunden_gesamt // 60 # 3 -sekunden = sekunden_gesamt % 60 # 35 - -# Mit :02d wird immer zweistellig mit führender Null formatiert: -print(f"{minuten:02d}:{sekunden:02d}") # "03:35" +minuten = self.dauer_sekunden // 60 +sekunden = self.dauer_sekunden % 60 +return f"{minuten:02d}:{sekunden:02d}" # "03:35" ``` --- ## 🎯 Deine Aufgabe: Der Spotify-Playlist-Manager -In `aufgabe.py` baust du deine eigene Musikverwaltung: -1. **Klasse `Song`**: - - Attribute: `titel`, `kuenstler`, `dauer_sekunden` - - Methode: `formatierte_dauer()` -> `"MM:SS"` - - `__str__()` -> `"{titel}" von {kuenstler} ({MM:SS})` -2. **Klasse `Playlist`**: - - `song_hinzufuegen(song)` - - `anzahl_songs()` - - `gesamtdauer_sekunden()` - - `finde_songs_von(kuenstler)` (Groß-/Kleinschreibung ignorieren!) - - `laengster_song()` (liefert das Song-Objekt mit der längsten Dauer) +In `aufgabe.py` baust du deine eigene Musikverwaltung mit `Song` und `Playlist`. ### Testen: ```bash diff --git a/05_objekte_kombinieren/index.html b/05_objekte_kombinieren/index.html index 9f11649..90ba9f3 100644 --- a/05_objekte_kombinieren/index.html +++ b/05_objekte_kombinieren/index.html @@ -25,60 +25,111 @@- + - + 1. Was ist Komposition?
- In großen Anwendungen (wie Spotify, Netflix oder Videospielen) arbeiten viele Klassen zusammen. Wenn eine Klasse Instanzen einer anderen Klasse beinhaltet, nennt man das Komposition (oder *"hat-ein"-Beziehung*): + In großen Anwendungen (wie Spotify, Netflix oder Schulsoftware) arbeiten viele Klassen zusammen. Wenn eine Klasse Objekte einer anderen Klasse als Attribute speichert, nennt man das Komposition (oder *"hat-ein"-Beziehung*):
+
- -- Eine Schulklasse hat viele Schüler.
- Eine Playlist hat viele Songs.
-- Ein Kino hat viele Säle und Filme.
+- Ein Kino hat viele Säle.
-🎧 Die Spotify-Analogie:- EinSongspeichert seinen Titel, den Künstler und die Länge in Sekunden. DiePlaylistkümmert sich um die Gesamtübersicht: Wie viele Songs gibt es? Wie lange dauert die Playlist insgesamt? Gibt es Lieder von Taylor Swift? -- + + +2. Nützliche Python-Kniffe
+2. 🎒 Vollständiges Beispiel: Schüler & Schulklasse Notenmanager
-⏱️ Sekunden in "MM:SS" umrechnen
-- Mit Ganzzahldivision
+//und Modulo%rechnen wir Sekunden in Minuten um: -Hier siehst du ein vollständiges Beispiel aus dem Schulalltag: Die Klasse
Schuelerspeichert Name und Note. Die KlasseSchulklasseverwaltet alle Schüler, berechnet den Notendurchschnitt und sucht die Klassenbesten:+- Python +-+ + + ++ Python (Komplettes Beispiel: schulklasse.py)gesamt_sekunden = 215 -minuten = gesamt_sekunden // 60 # 3 Minuten -sekunden = gesamt_sekunden % 60 # 35 Restsekunden ++# ============================================================================== +# KLASSE 1: Ein einzelner Schüler +# ============================================================================== +class Schueler: + def __init__(self, name, note): + self.name = name + self.note = float(note) -# :02d sorgt für zweistellige Zahlen mit führender Null (z.B. 03:05 statt 3:5): -zeit_text = f"{minuten:02d}:{sekunden:02d}" # "03:35"+ def __str__(self): + return f"{self.name} (Note: {self.note:.1f})" + + +# ============================================================================== +# KLASSE 2: Die Schulklasse verwaltet viele Schüler-Objekte +# ============================================================================== +class Schulklasse: + def __init__(self, klassen_name): + self.klassen_name = klassen_name + self.schueler_liste = [] + + def hinzufuegen(self, schueler): + self.schueler_liste.append(schueler) + + def notendurchschnitt(self): + if not self.schueler_liste: + return 0.0 + summe = sum(s.note for s in self.schueler_liste) + return summe / len(self.schueler_liste) + + def beste_schueler(self): + # Findet alle Schüler mit einer 1 (Note <= 1.5) + return [s for s in self.schueler_liste if s.note <= 1.5] + + +# Ausprobieren: +if __name__ == "__main__": + klasse_9a = Schulklasse("Klasse 9a") + + s1 = Schueler("Emma", 1.0) + s2 = Schueler("Lukas", 2.3) + s3 = Schueler("Mia", 1.3) + + klasse_9a.hinzufuegen(s1) + klasse_9a.hinzufuegen(s2) + klasse_9a.hinzufuegen(s3) + + print(f"Durchschnitt: {klasse_9a.notendurchschnitt():.2f}") # 1.53 + + print("\nBeste Schüler:") + for einserschueler in klasse_9a.beste_schueler(): + print(f"- {einserschueler}")+ - +3. Nützliche Kniffe für die Song-Aufgabe
+ +⏱️ Sekunden in "MM:SS" umrechnen
++minuten = self.dauer_sekunden // 60 +sekunden = self.dauer_sekunden % 60 +return f"{minuten:02d}:{sekunden:02d}" # z.B. "03:35"🔍 Groß- und Kleinschreibung beim Suchen ignorieren
-- Damit
-"Taylor Swift"auch gefunden wird, wenn jemand"taylor swift"eingibt, nutzen wir.lower(): --if song.kuenstler.lower() == gesuchter_kuenstler.lower(): +if song.kuenstler.lower() == kuenstler.lower(): treffer.append(song)- 3. Deine Aufgaben in
+aufgabe.py4. 🎯 Deine Aufgaben in
aufgabe.py@@ -110,7 +161,7 @@
- @@ -102,7 +153,7 @@
💡 Lösungshinweise (Aufklappen bei Bedarf)
-Tipp zum längsten Song finden
+🔍 Tipp zum längsten Song finden
def laengster_song(self): @@ -127,9 +178,9 @@ - +- 4. Lösung überprüfen
+5. 🧪 Lösung überprüfen
Führe im Terminal im Ordner
05_objekte_kombinierenfolgenden Befehl aus:diff --git a/06_abschlussprojekt_tamagotchi/README.md b/06_abschlussprojekt_tamagotchi/README.md index e8bd336..fca6c3f 100644 --- a/06_abschlussprojekt_tamagotchi/README.md +++ b/06_abschlussprojekt_tamagotchi/README.md @@ -7,24 +7,56 @@ Herzlichen Glückwunsch! Du hast alle grundlegenden Konzepte der objektorientier - `__str__` für ansprechende Textausgaben - Beziehungen zwischen Objekten -Jetzt setzen wir alles in einem **vollwertigen, interaktiven Mini-Projekt** zusammen: Einem virtuellen Haustier (Tamagotchi)! +--- + +## 🤖 Vollständiges Beispiel: Roboter mit Lebenszyklus + +```python +class Roboter: + def __init__(self, name): + self.name = name + self.energie = 100 + self.ist_aktiv = True + + def _begrenzen(self, wert): + return max(0, min(100, wert)) + + def arbeiten(self, stunden): + if not self.ist_aktiv: + return f"{self.name} ist ausgeschaltet!" + verbrauch = stunden * 20 + self.energie = self._begrenzen(self.energie - verbrauch) + if self.energie == 0: + self.ist_aktiv = False + return f"{self.name} schaltet sich ab!" + return f"{self.name} hat gearbeitet (Energie: {self.energie}%)" + + def aufladen(self): + self.energie = 100 + self.ist_aktiv = True + return f"{self.name} ist wieder voll!" + + def __str__(self): + status = "Aktiv ⚡" if self.ist_aktiv else "Ausgeschaltet 💤" + return f"[{self.name}] Energie: {self.energie}% | Status: {status}" + +# Testen: +bot = Roboter("Wall-E") +print(bot) +print(bot.arbeiten(3)) +print(bot) +print(bot.aufladen()) +``` --- ## 🎮 Wie funktioniert das Tamagotchi? -Dein Tamagotchi hat Eigenschaften, die sich durch deine Aktionen (und mit der Zeit) verändern: -- **Hunger** (0 = vollgefressen, 100 = verhungert) -- **Müdigkeit** (0 = voller Energie, 100 = total erschöpft) -- **Glück** (0 = unglücklich, 100 = überglücklich) +- **Hunger** (0 bis 100) +- **Müdigkeit** (0 bis 100) +- **Glück** (0 bis 100) - **Alter in Tagen** -Du kannst mit ihm interagieren: -- 🍎 **Füttern** (`fuettern`): Senkt den Hunger, macht etwas müde und etwas glücklicher. -- ⚽ **Spielen** (`spielen`): Steigert das Glück, macht aber hungrig und müde. Zu müde Haustiere weigern sich zu spielen! -- 💤 **Schlafen** (`schlafen`): Setzt die Müdigkeit auf 0, lässt einen Tag vergehen (`alter_tage += 1`), macht aber etwas hungrig. -- ⏳ **Zeit vergeht** (`zeit_vergeht`): Das Haustier wird hungriger, müder und etwas trauriger. Wenn der Hunger 100 erreicht oder Glück 0 wird, schläft es für immer ein... - --- ## 🕹️ Das interaktive Spiel @@ -34,7 +66,6 @@ Sobald du die `Tamagotchi`-Klasse in `aufgabe.py` fertig programmiert hast und a ```bash python3 tamagotchi_spiel.py ``` -Dort kannst du deinem Haustier einen Namen geben und dich live um es kümmern! --- diff --git a/06_abschlussprojekt_tamagotchi/index.html b/06_abschlussprojekt_tamagotchi/index.html index f2de1d3..f2a570a 100644 --- a/06_abschlussprojekt_tamagotchi/index.html +++ b/06_abschlussprojekt_tamagotchi/index.html @@ -19,73 +19,119 @@AbschlussprojektDein eigenes Tamagotchi (Virtuelles Haustier) 🥚🐣
-Kombiniere alle Konzepte in einem interaktiven, voll funktionsfähigen Konsolenspiel!
+Kombiniere alle gelernten OOP-Konzepte in einem interaktiven, voll funktionsfähigen Konsolenspiel!
- + - 1. Das große Finale! 🏆
- Du hast alle Grundlagen gelernt: Klassen definieren,
-__init__&selfnutzen, Methoden schreiben,__str__gestalten und Objekte verwalten. -- Jetzt bauen wir ein komplettes, lebendiges Tamagotchi, das du im Terminal füttern, schlafen legen und mit dem du spielen kannst! + Du hast alle Grundlagen gemeistert: Klassen & Konstruktoren, Methoden,
+__str__und Objekt-Beziehungen. Jetzt bauen wir ein komplettes, virtuelles Haustier (Tamagotchi), das du im Terminal füttern, schlafen legen und mit dem du spielen kannst!-🎮 Wie das Spiel funktioniert:--
+ +- 🍖 Hunger (0 bis 100): Steigt mit der Zeit, sinkt beim Füttern. Bei 100 stirbt das Haustier!
-- 💤 Müdigkeit (0 bis 100): Steigt bei Aktionen. Bei über 80 weigert es sich zu spielen. Schlafen setzt Müdigkeit auf 0.
-- 💖 Glück (0 bis 100): Steigt beim Spielen, sinkt mit der Zeit. Bei 0 stirbt das Haustier vor Einsamkeit.
-- 📅 Alter: Bei jedem Schlafen vergeht ein neuer Tag (
-alter_tage += 1).+ - +2. 🤖 Vollständiges Beispiel: Ein Roboter mit Lebenszyklus
+ +Bevor du das Tamagotchi baust, schau dir dieses vollständige Beispiel an. Es zeigt, wie Attribute begrenzt werden (Clamping 0-100) und wie ein Status überprüft wird:
+ +++++ + + ++ Python (Komplettes Beispiel: roboter.py) +class Roboter: + def __init__(self, name): + self.name = name + self.energie = 100 # 100% Start-Energie + self.ist_aktiv = True + + # Hilfsmethode, um Werte zwischen 0 und 100 zu halten: + def _begrenzen(self, wert): + return max(0, min(100, wert)) + + def arbeiten(self, dauer_stunden): + if not self.ist_aktiv: + return f"{self.name} ist ausgeschaltet!" + + verbrauch = dauer_stunden * 20 + self.energie = self._begrenzen(self.energie - verbrauch) + + if self.energie == 0: + self.ist_aktiv = False + return f"{self.name} hat keine Energie mehr und schaltet sich ab!" + + return f"{self.name} hat {dauer_stunden}h gearbeitet. Restenergie: {self.energie}%" + + def aufladen(self): + self.energie = 100 + self.ist_aktiv = True + return f"{self.name} ist wieder voll aufgeladen!" + + def __str__(self): + status = "Aktiv ⚡" if self.ist_aktiv else "Ausgeschaltet 💤" + return f"[{self.name}] Energie: {self.energie}% | Status: {status}" + + +# Ausprobieren: +if __name__ == "__main__": + bot = Roboter("Wall-E") + print(bot) + print(bot.arbeiten(3)) # Verbraucht 60% -> 40% übrig + print(bot.arbeiten(3)) # Energie auf 0 -> schaltet ab + print(bot) + print(bot.aufladen())- 2. Deine Aufgaben in
+aufgabe.py3. 🎯 Deine Aufgaben in
aufgabe.py@@ -93,9 +139,9 @@
💡 Lösungshinweise (Aufklappen bei Bedarf)
-Tipp zur Werte-Begrenzung (Clamping)
+🔍 Tipp zur Werte-Begrenzung (Clamping)
-Damit Werte nicht negativ werden oder 100 überschreiten, kannst du die Hilfsfunktion
+max(0, min(100, wert))nutzen:Damit Werte nicht unter 0 fallen oder über 100 steigen, nutze
max(0, min(100, wert)):@@ -103,11 +149,11 @@ - +self.hunger = max(0, min(100, self.hunger - menge))- 3. Das interaktive Spiel starten! 🕹️
+4. 🕹️ Das interaktive Spiel starten!
-Sobald deine Tests grün sind, kannst du das Spiel live spielen:
+Sobald alle Unittests grün sind, kannst du das Spiel live spielen:
@@ -117,8 +163,8 @@-🎉 Geschafft!- Du hast damit erfolgreich gelernt, wie man objektorientiert in Python programmiert! +🎉 Du hast es geschafft!+ Herzlichen Glückwunsch zum erfolgreichen Abschluss der Python OOP Übungsreihe!