Füge vollständige, praxisnahe Klassenbeispiele in alle HTML-Seiten und READMEs ein

This commit is contained in:
Alex Mueller 2026-08-29 13:03:42 +02:00
parent fbaec82182
commit 35f57ac484
12 changed files with 778 additions and 429 deletions

View file

@ -37,48 +37,47 @@ Beim Dictionary kann man sich schnell bei Schlüsseln vertippen. Eine Klasse gib
---
## 💻 Wie sieht eine Klasse in Python aus?
## 🌟 Vollständiges Praxisbeispiel: Der Fahrrad-Verleih
Eine einfache Klasse definierst du mit dem Schlüsselwort `class`:
Hier siehst du ein komplettes, funktionierendes Beispiel:
```python
class Auto:
pass # 'pass' bedeutet: "Hier passiert erst mal nichts weiter"
# 1. Bauplan definieren:
class Fahrrad:
pass
# 2. Hilfsfunktion, die mit Fahrrad-Objekten arbeitet:
def fahrrad_info(bike):
return f"{bike.marke} ({bike.farbe}) - {bike.gaenge} Gänge - {bike.preis_pro_tag}€/Tag"
# 3. Zwei konkrete Fahrräder (Objekte) erstellen:
mountainbike = Fahrrad()
mountainbike.marke = "Cube"
mountainbike.farbe = "Schwarz/Grün"
mountainbike.gaenge = 21
mountainbike.preis_pro_tag = 25.0
citybike = Fahrrad()
citybike.marke = "Gazelle"
citybike.farbe = "Himmelblau"
citybike.gaenge = 7
citybike.preis_pro_tag = 15.0
# 4. Ausgabe:
print("Rad 1:", fahrrad_info(mountainbike))
print("Rad 2:", fahrrad_info(citybike))
```
Aus dieser Klasse kannst du nun ein Objekt erzeugen (**Instanziierung**):
```python
# Objekt erstellen:
mein_auto = Auto()
# Eigenschaften (Attribute) zuweisen mit dem Punkt (.):
mein_auto.farbe = "Rot"
mein_auto.marke = "VW"
mein_auto.ps = 110
print(mein_auto.farbe) # Gibt "Rot" aus
```
Du kannst ganz einfach ein zweites Auto bauen:
```python
dein_auto = Auto()
dein_auto.farbe = "Blau"
dein_auto.marke = "BMW"
dein_auto.ps = 180
```
`mein_auto` und `dein_auto` sind zwei völlig eigenständige Objekte, die aus demselben Bauplan `Auto` entstanden sind!
---
## ⚠️ Häufige Stolperfallen für Einsteiger
1. **Groß- und Kleinschreibung:**
- Klassen werden per Konvention in **CamelCase** mit großem Anfangsbuchstaben geschrieben: `class Haustier:`, `class BankKonto:`.
- Variablen und Funktionen schreibt man klein mit Unterstrichen: `mein_haustier = Haustier()`.
2. **Klammern beim Erstellen nicht vergessen:**
1. **Klammern beim Erstellen nicht vergessen:**
- `bello = Haustier()` erzeugt ein neues Objekt.
- `bello = Haustier` (ohne Klammern) würde die Klasse selbst speichern, kein neues Objekt erzeugen!
2. **Groß- und Kleinschreibung:**
- Klassen werden per Konvention in **CamelCase** mit großem Anfangsbuchstaben geschrieben: `class Haustier:`, `class Fahrrad:`.
- Variablen und Funktionen schreibt man klein: `mein_tier`, `fahrrad_info()`.
3. **`return` in Funktionen nicht vergessen:**
- Wenn deine Funktion ein neu gebautes Haustier erzeugen soll, muss am Ende `return tier` stehen, sonst gibt die Funktion `None` zurück.
@ -86,7 +85,7 @@ dein_auto.ps = 180
## 🎯 Deine Aufgaben in `aufgabe.py`
Öffne jetzt die Datei `aufgabe.py` und bearbeite die nummerierten TODOs:
Öffne die Datei `aufgabe.py` und bearbeite die nummerierten TODOs:
1. **TODO 1:** Definiere die leere Klasse `Haustier`.
2. **TODO 2:** Schreibe die Funktion `erstelle_bello()`.
3. **TODO 3:** Schreibe die Funktion `erstelle_mimi()`.
@ -94,7 +93,6 @@ dein_auto.ps = 180
5. **TODO 5:** Schreibe die Funktion `aelteres_tier(tier1, tier2)`.
### Testen:
Führe deine Tests aus mit:
```bash
python3 test_aufgabe.py
```

View file

@ -17,54 +17,35 @@
</nav>
<div class="header-badge">Kapitel 01</div>
<h1>Die erste Klasse: Bauplan vs. Objekt 🐶</h1>
<p>Verstehe den Unterschied zwischen einer Klasse und einer Instanz und baue deine ersten Haustier-Objekte.</p>
<p>Verstehe den Unterschied zwischen einer Klasse und einer Instanz anhand vollständiger Praxisbeispiele.</p>
</div>
</header>
<main class="container">
<!-- Theorie Card -->
<!-- 1. Theorie & Alltagsanalogie -->
<section class="card">
<h2>1. Die wichtigste Idee: Bauplan vs. Haus</h2>
<h2>1. Die Grundidee: Bauplan vs. Echtes Objekt</h2>
<p>
In Python ist alles, was du bisher kennengelernt hast (Zahlen, Strings, Listen, Dictionaries), im Grunde ein <strong>Objekt</strong>. Doch jetzt lernst du, wie du <strong>deine ganz eigenen Datentypen</strong> erfindest!
In Python ist fast alles ein <strong>Objekt</strong> (Zahlen, Texte, Listen). Mit <strong>Klassen</strong> lernst du jetzt das mächtigste Werkzeug der Programmierung kennen: <strong>Deine eigenen Baupläne zu entwerfen!</strong>
</p>
<div class="box box-analogie">
<div class="box-title">🏗️ Die Plätzchenform-Analogie:</div>
<p>Stell dir das Backen vor:</p>
<ul style="margin-left: 20px;">
<li>Die <strong>Klasse (<code>class</code>)</strong> ist die <strong>Ausstechform</strong>. Sie legt fest: Jedes Plätzchen hat einen Kopf, zwei Arme und zwei Beine. Die Form selbst kann man aber nicht essen.</li>
<li>Das <strong>Objekt (Instanz)</strong> ist das <strong>echte Plätzchen</strong>, das du aus dem Teig ausstichst. Ein Plätzchen bekommt Schokoglasur, das andere Zuckerstreusel. Beide stammen aus derselben Form, sind aber eigenständig!</li>
<p>Stell dir das Backen in der Küche vor:</p>
<ul style="margin-left: 20px; margin-top: 8px;">
<li>Die <strong>Klasse (<code>class</code>)</strong> ist die <strong>Ausstechform</strong>. Sie legt die Form fest (Kopf, Arme, Beine). Die Form selbst kann man nicht essen.</li>
<li>Das <strong>Objekt (Instanz)</strong> ist das <strong>echte Plätzchen</strong>, 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!</li>
</ul>
</div>
<h3>Warum nicht einfach Dictionaries?</h3>
<p>Ein Dictionary hat keine feste Struktur – man vertippt sich leicht:</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Problem mit Dictionaries)</span>
</div>
<pre><span class="var">tier1</span> = {<span class="str">"name"</span>: <span class="str">"Bello"</span>, <span class="str">"tierart"</span>: <span class="str">"Hund"</span>, <span class="str">"alter"</span>: <span class="num">3</span>}
<span class="var">tier2</span> = {<span class="str">"name"</span>: <span class="str">"Mimi"</span>, <span class="str">"art"</span>: <span class="str">"Katze"</span>, <span class="str">"alter"</span>: <span class="num">5</span>} <span class="cm"># Ups! 'art' statt 'tierart'!</span>
<span class="cm"># Ein Programm würde hier abstürzen, weil tier2["tierart"] nicht existiert!</span></pre>
</div>
<p>Mit einer <strong>Klasse</strong> definierst du eine klare, wiederverwendbare Struktur.</p>
</section>
<!-- Syntax Card -->
<!-- 2. Vergleich: Vorher vs. Nachher -->
<section class="card">
<h2>2. Wie definiert und nutzt man eine Klasse?</h2>
<p>Eine einfache Klasse erstellst du mit dem Schlüsselwort <code>class</code>:</p>
<h2>2. Warum machen Klassen deinen Code besser?</h2>
<p>Schauen wir uns an, wie man Daten bisher mit Dictionaries gespeichert hat – und warum eine Klasse viel übersichtlicher und sicherer ist:</p>
<div class="code-container">
<div class="code-header">
@ -73,35 +54,151 @@
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python</span>
<span>❌ Vorher: Mit Dictionaries (Fehleranfällig!)</span>
</div>
<pre><span class="cm"># 1. Bauplan definieren:</span>
<span class="kw">class</span> <span class="fn">Auto</span>:
<span class="kw">pass</span> <span class="cm"># pass bedeutet: Hier steht erst mal kein weiterer Code</span>
<pre><span class="cm"># Hund 1 mit Dictionary</span>
<span class="var">hund1</span> = {<span class="str">"name"</span>: <span class="str">"Bello"</span>, <span class="str">"rasse"</span>: <span class="str">"Labrador"</span>, <span class="str">"alter"</span>: <span class="num">3</span>}
<span class="cm"># 2. Ein Objekt erzeugen (Instanziierung):</span>
<span class="var">mein_auto</span> = <span class="fn">Auto</span>()
<span class="cm"># Hund 2: Ups! Hier haben wir uns beim Schlüssel vertippt ("tier_rasse" statt "rasse")!</span>
<span class="var">hund2</span> = {<span class="str">"name"</span>: <span class="str">"Luna"</span>, <span class="str">"tier_rasse"</span>: <span class="str">"Pudel"</span>, <span class="str">"alter"</span>: <span class="num">2</span>}
<span class="cm"># 3. Eigenschaften (Attribute) mit dem Punkt (.) setzen:</span>
<span class="var">mein_auto</span>.<span class="attr">farbe</span> = <span class="str">"Rot"</span>
<span class="var">mein_auto</span>.<span class="attr">marke</span> = <span class="str">"VW"</span>
<span class="var">mein_auto</span>.<span class="attr">ps</span> = <span class="num">110</span>
<span class="cm"># Wenn wir jetzt die Rasse ausgeben wollen:</span>
<span class="fn">print</span>(<span class="var">hund1</span>[<span class="str">"rasse"</span>]) <span class="cm"># Funktioniert -> "Labrador"</span>
<span class="fn">print</span>(<span class="var">hund2</span>[<span class="str">"rasse"</span>]) <span class="cm"># 💥 KeyError: 'rasse' existiert nicht! Programm stürzt ab!</span></pre>
</div>
<span class="cm"># 4. Werte wieder abfragen:</span>
<span class="fn">print</span>(<span class="var">mein_auto</span>.<span class="attr">farbe</span>) <span class="cm"># Gibt "Rot" aus</span></pre>
<p>Jetzt das Ganze mit einer <strong>Klasse</strong>:</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>✅ Nachher: Mit einer Klasse (Sauber &amp; Einheitlich)</span>
</div>
<pre><span class="cm"># 1. Wir definieren den gemeinsamen Bauplan:</span>
<span class="kw">class</span> <span class="fn">Hund</span>:
<span class="kw">pass</span>
<span class="cm"># 2. Wir erstellen zwei konkrete Hunde (Instanzen):</span>
<span class="var">bello</span> = <span class="fn">Hund</span>()
<span class="var">bello</span>.<span class="attr">name</span> = <span class="str">"Bello"</span>
<span class="var">bello</span>.<span class="attr">rasse</span> = <span class="str">"Labrador"</span>
<span class="var">bello</span>.<span class="attr">alter</span> = <span class="num">3</span>
<span class="var">luna</span> = <span class="fn">Hund</span>()
<span class="var">luna</span>.<span class="attr">name</span> = <span class="str">"Luna"</span>
<span class="var">luna</span>.<span class="attr">rasse</span> = <span class="str">"Pudel"</span>
<span class="var">luna</span>.<span class="attr">alter</span> = <span class="num">2</span>
<span class="cm"># 3. Jetzt greifen wir mit der Punkt-Notation (.) auf die Eigenschaften zu:</span>
<span class="fn">print</span>(<span class="var">bello</span>.<span class="attr">name</span>, <span class="str">"ist ein"</span>, <span class="var">bello</span>.<span class="attr">rasse</span>) <span class="cm"># Ausgabe: Bello ist ein Labrador</span>
<span class="fn">print</span>(<span class="var">luna</span>.<span class="attr">name</span>, <span class="str">"ist ein"</span>, <span class="var">luna</span>.<span class="attr">rasse</span>) <span class="cm"># Ausgabe: Luna ist ein Pudel</span></pre>
</div>
</section>
<!-- 3. Vollständiges, ausführliches Praxisbeispiel -->
<section class="card">
<h2>3. 🌟 Vollständiges Praxisbeispiel: Der Fahrrad-Verleih</h2>
<p>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:</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Komplettes Beispiel: fahrrad_verleih.py)</span>
</div>
<pre><span class="cm"># ==============================================================================</span>
<span class="cm"># SCHRITT 1: Die Klasse (der Bauplan) definieren</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">class</span> <span class="fn">Fahrrad</span>:
<span class="kw">pass</span>
<span class="cm"># ==============================================================================</span>
<span class="cm"># SCHRITT 2: Eine Funktion, die Fahrräder beschreibt</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">def</span> <span class="fn">fahrrad_info</span>(<span class="var">bike</span>):
<span class="cm"># Wir greifen über den Punkt auf die Attribute des übergebenen Objekts zu:</span>
<span class="kw">return</span> <span class="str">f"{bike.marke} ({bike.farbe}) - {bike.gaenge} Gänge - {bike.preis_pro_tag}€/Tag"</span>
<span class="cm"># ==============================================================================</span>
<span class="cm"># SCHRITT 3: Eine Funktion, die prüft, welches Fahrrad günstiger ist</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">def</span> <span class="fn">guenstigeres_rad</span>(<span class="var">rad_a</span>, <span class="var">rad_b</span>):
<span class="kw">if</span> <span class="var">rad_a</span>.<span class="attr">preis_pro_tag</span> &lt; <span class="var">rad_b</span>.<span class="attr">preis_pro_tag</span>:
<span class="kw">return</span> <span class="var">rad_a</span>
<span class="kw">else</span>:
<span class="kw">return</span> <span class="var">rad_b</span>
<span class="cm"># ==============================================================================</span>
<span class="cm"># SCHRITT 4: Wir erzeugen konkrete Objekte und probieren alles aus!</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="cm"># Erstes Fahrrad-Objekt erstellen:</span>
<span class="var">mountainbike</span> = <span class="fn">Fahrrad</span>()
<span class="var">mountainbike</span>.<span class="attr">marke</span> = <span class="str">"Cube"</span>
<span class="var">mountainbike</span>.<span class="attr">farbe</span> = <span class="str">"Schwarz/Grün"</span>
<span class="var">mountainbike</span>.<span class="attr">gaenge</span> = <span class="num">21</span>
<span class="var">mountainbike</span>.<span class="attr">preis_pro_tag</span> = <span class="num">25.0</span>
<span class="cm"># Zweites Fahrrad-Objekt erstellen:</span>
<span class="var">citybike</span> = <span class="fn">Fahrrad</span>()
<span class="var">citybike</span>.<span class="attr">marke</span> = <span class="str">"Gazelle"</span>
<span class="var">citybike</span>.<span class="attr">farbe</span> = <span class="str">"Himmelblau"</span>
<span class="var">citybike</span>.<span class="attr">gaenge</span> = <span class="num">7</span>
<span class="var">citybike</span>.<span class="attr">preis_pro_tag</span> = <span class="num">15.0</span>
<span class="cm"># Infos ausgeben:</span>
<span class="fn">print</span>(<span class="str">"Verfügbare Räder:"</span>)
<span class="fn">print</span>(<span class="str">"1."</span>, <span class="fn">fahrrad_info</span>(<span class="var">mountainbike</span>))
<span class="fn">print</span>(<span class="str">"2."</span>, <span class="fn">fahrrad_info</span>(<span class="var">citybike</span>))
<span class="cm"># Günstigeres Rad finden:</span>
<span class="var">schnaeppchen</span> = <span class="fn">guenstigeres_rad</span>(<span class="var">mountainbike</span>, <span class="var">citybike</span>)
<span class="fn">print</span>(<span class="str">f"\nDas günstigere Rad ist das {schnaeppchen.marke} für nur {schnaeppchen.preis_pro_tag}€!"</span>)</pre>
</div>
<div class="box box-success">
<div class="box-title">💡 Was du hier sehen kannst:</div>
<code>mountainbike</code> und <code>citybike</code> sind zwei getrennte Variablen im Arbeitsspeicher. Jedes hat seine eigenen Werte für <code>.marke</code>, <code>.farbe</code> und <code>.preis_pro_tag</code>, obwohl beide aus der Klasse <code>Fahrrad</code> stammen!
</div>
</section>
<!-- 4. Stolperfallen -->
<section class="card">
<h2>4. ⚠️ Häufige Stolperfallen für Einsteiger</h2>
<div class="box box-warning">
<div class="box-title">1. Klammern beim Erstellen vergessen:</div>
<code>mein_rad = Fahrrad()</code> &nbsp;&check; (Richtig: Erzeugt ein neues Objekt!)<br>
<code>mein_rad = Fahrrad</code> &nbsp;&cross; (Falsch: Speichert nur den Bauplan in die Variable!)
</div>
<div class="box box-warning">
<div class="box-title">⚠️ Häufige Stolperfalle: Klassenname Großschreiben!</div>
In Python schreibt man Klassennamen standardmäßig in <strong>CamelCase</strong> mit großem Anfangsbuchstaben (z.B. <code>Haustier</code>, <code>BankKonto</code>), während Variablen und Funktionen klein geschrieben werden (z.B. <code>mein_haustier</code>, <code>erstelle_tier()</code>).
<div class="box-title">2. Groß- und Kleinschreibung:</div>
Klassennamen beginnen in Python immer mit einem <strong>Großbuchstaben</strong> (<code>Haustier</code>, <code>Fahrrad</code>). Variablen und Funktionsnamen schreibt man klein (<code>bello</code>, <code>erstelle_bello()</code>).
</div>
<div class="box box-danger">
<div class="box-title">3. 'return' in Funktionen vergessen:</div>
Wenn eine Funktion ein Haustier bauen soll (wie <code>erstelle_bello()</code>), muss am Ende <strong>unbedingt</strong> <code>return mein_tier</code> stehen! Ohne <code>return</code> gibt Python automatisch <code>None</code> zurück.
</div>
</section>
<!-- Aufgaben Card -->
<!-- 5. Aufgabenstellung -->
<section class="card">
<h2>3. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>5. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<p>Öffne die Datei <code>01_einstieg_klassen/aufgabe.py</code> und bearbeite die nummerierten TODOs:</p>
<p>Öffne die Datei <code>01_einstieg_klassen/aufgabe.py</code> in deinem Editor und bearbeite die Aufgaben:</p>
<ul class="task-list">
<li class="task-item">
@ -113,66 +210,66 @@
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t2">
<label for="t2" class="task-label">
<strong>TODO 2:</strong> Funktion <code>erstelle_bello()</code>: Erzeuge ein Haustier-Objekt mit <code>name="Bello"</code>, <code>tierart="Hund"</code>, <code>alter=3</code> und gib es mit <code>return</code> zurück.
<strong>TODO 2:</strong> Schreibe <code>erstelle_bello()</code>: Erzeuge ein Haustier-Objekt, setze <code>name="Bello"</code>, <code>tierart="Hund"</code>, <code>alter=3</code> und gib es mit <code>return</code> zurück.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t3">
<label for="t3" class="task-label">
<strong>TODO 3:</strong> Funktion <code>erstelle_mimi()</code>: Erzeuge ein Haustier-Objekt mit <code>name="Mimi"</code>, <code>tierart="Katze"</code>, <code>alter=5</code> und gib es zurück.
<strong>TODO 3:</strong> Schreibe <code>erstelle_mimi()</code>: Erzeuge ein Haustier-Objekt, setze <code>name="Mimi"</code>, <code>tierart="Katze"</code>, <code>alter=5</code> und gib es zurück.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t4">
<label for="t4" class="task-label">
<strong>TODO 4:</strong> Funktion <code>steckbrief_text(haustier)</code>: Gibt einen f-String zurück: <code>"{haustier.name} ist ein(e) {haustier.tierart} und ist {haustier.alter} Jahre alt."</code>
<strong>TODO 4:</strong> Schreibe <code>steckbrief_text(haustier)</code>: Gibt den formatierten Text <code>"{haustier.name} ist ein(e) {haustier.tierart} und ist {haustier.alter} Jahre alt."</code> zurück.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t5">
<label for="t5" class="task-label">
<strong>TODO 5:</strong> Funktion <code>aelteres_tier(tier1, tier2)</code>: Vergleicht <code>tier1.alter</code> und <code>tier2.alter</code> und gibt das ältere Haustier-Objekt zurück (bei Gleichstand <code>tier1</code>).
<strong>TODO 5:</strong> Schreibe <code>aelteres_tier(tier1, tier2)</code>: Vergleicht <code>tier1.alter</code> und <code>tier2.alter</code> und gibt das ältere Tier zurück (bei Gleichstand <code>tier1</code>).
</label>
</li>
</ul>
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<h3>💡 Lösungshinweise (Aufklappen, wenn du Hilfe brauchst)</h3>
<details>
<summary>Tipp zu TODO 1 & 2 (Objekt erstellen und befüllen)</summary>
<summary>🔍 Tipp zu TODO 1 &amp; 2 (Klasse &amp; Objekt erstellen)</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="kw">class</span> <span class="fn">Haustier</span>:
<span class="kw">pass</span>
<span class="kw">def</span> <span class="fn">erstelle_bello</span>():
<span class="var">tier</span> = <span class="fn">Haustier</span>() <span class="cm"># Neues Objekt erzeugen</span>
<span class="var">tier</span>.<span class="attr">name</span> = <span class="str">"Bello"</span>
<span class="var">tier</span> = <span class="fn">Haustier</span>() <span class="cm"># 1. Neues Haustier-Objekt bauen</span>
<span class="var">tier</span>.<span class="attr">name</span> = <span class="str">"Bello"</span> <span class="cm"># 2. Attribute zuweisen</span>
<span class="var">tier</span>.<span class="attr">tierart</span> = <span class="str">"Hund"</span>
<span class="var">tier</span>.<span class="attr">alter</span> = <span class="num">3</span>
<span class="kw">return</span> <span class="var">tier</span> <span class="cm"># WICHTIG: Das fertige Objekt zurückgeben!</span></pre>
<span class="kw">return</span> <span class="var">tier</span> <span class="cm"># 3. Objekt zurückgeben!</span></pre>
</div>
</div>
</details>
<details>
<summary>Tipp zu TODO 5 (Tiere vergleichen)</summary>
<summary>🔍 Tipp zu TODO 5 (Tiere vergleichen)</summary>
<div class="details-content">
<p>Du kannst mit einem einfachen <code>if</code> auf die Attribute der übergebenen Objekte zugreifen:</p>
<div class="code-container">
<pre><span class="kw">if</span> <span class="var">tier2</span>.<span class="attr">alter</span> > <span class="var">tier1</span>.<span class="attr">alter</span>:
<span class="kw">return</span> <span class="var">tier2</span>
<span class="kw">else</span>:
<span class="kw">return</span> <span class="var">tier1</span></pre>
<pre><span class="kw">def</span> <span class="fn">aelteres_tier</span>(<span class="var">tier1</span>, <span class="var">tier2</span>):
<span class="kw">if</span> <span class="var">tier2</span>.<span class="attr">alter</span> > <span class="var">tier1</span>.<span class="attr">alter</span>:
<span class="kw">return</span> <span class="var">tier2</span>
<span class="kw">else</span>:
<span class="kw">return</span> <span class="var">tier1</span></pre>
</div>
</div>
</details>
</section>
<!-- Testen & Footer Navigation -->
<!-- 6. Testen & Navigation -->
<section class="card">
<h2>4. Lösung überprüfen</h2>
<p>Führe im Terminal im Ordner <code>01_einstieg_klassen</code> folgenden Befehl aus:</p>
<h2>6. 🧪 Lösung überprüfen</h2>
<p>Öffne das Terminal und führe den Test aus:</p>
<div class="code-container">
<div class="code-header">
<span>Terminal</span>

View file

@ -16,64 +16,49 @@ Deshalb gibt es in Python den **Konstruktor**: `__init__`.
`__init__` steht für *initialisieren* (vorbereiten/startklar machen).
Es ist eine **spezielle Methode**, die Python **automatisch aufruft**, sobald du ein neues Objekt erstellst:
Es ist eine **spezielle Methode**, die Python **automatisch aufruft**, sobald du ein neues Objekt erstellst.
---
## 📱 Vollständiges Praxisbeispiel: Die Smartphone-Klasse
```python
class Haustier:
def __init__(self, name, tierart, alter):
self.name = name
self.tierart = tierart
self.alter = alter
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%
# Jetzt können wir die Werte direkt in die Klammern schreiben!
bello = Haustier("Bello", "Hund", 3)
mimi = Haustier("Mimi", "Katze", 5)
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!"
print(bello.name) # Gibt sofort "Bello" aus
def aufladen(self):
self.akku = 100
return f"{self.modell} ist wieder voll aufgeladen (100%)!"
# Verwendung:
mein_handy = Smartphone("iPhone 15", 256)
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%
```
Die doppelten Unterstriche `__` nennt man in Python auch **Dunder** (Double Underscore). Sie signalisieren besondere Python-Funktionen.
---
## 🪞 Was bedeutet eigentlich `self`?
`self` verwirrt am Anfang fast jeden – ist aber ganz einfach:
- `self` bedeutet auf Deutsch **"ich selbst"** oder **"dieses Objekt hier"**.
- Wenn du `bello = Haustier("Bello", "Hund", 3)` aufrufst, übergibt Python das neu entstandene `bello`-Objekt automatisch als erstes Argument `self`.
- `self.name = name` bedeutet also: *"Speichere den übergebenen Namen in MEINEM EIGENEN Attribut `.name` ab!"*
```
Haustier("Bello", "Hund", 3)
│
▼
def __init__(self, name, tierart, alter):
▲ │ │ │
│ ▼ ▼ ▼
bello "Bello" "Hund" 3
│
├── bello.name = "Bello"
├── bello.tierart = "Hund"
└── bello.alter = 3
```
---
## ⚙️ Standardwerte (Default Parameters)
Manchmal hat ein Attribut einen typischen Startwert (z.B. ein neues Bankkonto startet meist bei `0.0` Euro):
```python
class Bankkonto:
def __init__(self, inhaber, kontostand=0.0):
self.inhaber = inhaber
self.kontostand = kontostand
# Konto mit 0.0 Euro Startguthaben:
k1 = Bankkonto("Anna")
# Konto mit speziellem Startguthaben:
k2 = Bankkonto("Ben", 50.0)
```
- `self` bedeutet auf Deutsch **"ich selbst"** oder **"dieses konkrete Objekt hier"**.
- Wenn du `mein_handy.benutzen(30)` aufrufst, übergibt Python das neu entstandene `mein_handy`-Objekt automatisch als erstes Argument `self`.
- `self.akku -= verbrauch` zieht den Strom genau vom Akku dieses einen Handys ab.
---

View file

@ -19,43 +19,36 @@
</nav>
<div class="header-badge">Kapitel 02</div>
<h1>Der Konstruktor <code>__init__</code> &amp; das geheimnisvolle <code>self</code> 💳</h1>
<p>Lerne, wie Objekte direkt beim Erstellen startklar gemacht werden und baue eine Taschengeld-Konto App.</p>
<p>Lerne, wie Objekte direkt beim Erstellen startklar gemacht werden – mit vollständigen Codebeispielen.</p>
</div>
</header>
<main class="container">
<!-- Theorie Card -->
<!-- 1. Warum __init__ -->
<section class="card">
<h2>1. Warum brauchen wir <code>__init__</code>?</h2>
<p>
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:
</p>
<div class="code-container">
<pre><span class="var">bello</span> = <span class="fn">Haustier</span>()
<span class="var">bello</span>.<span class="attr">name</span> = <span class="str">"Bello"</span>
<span class="var">bello</span>.<span class="attr">alter</span> = <span class="num">3</span> <span class="cm"># Was passiert, wenn man hier das Alter vergisst? -> Programm stürzt ab!</span></pre>
<span class="var">bello</span>.<span class="attr">alter</span> = <span class="num">3</span> <span class="cm"># Wenn wir 100 Tiere haben, müssen wir hunderte Zeilen schreiben!</span></pre>
</div>
<p>
Deshalb gibt es den <strong>Konstruktor</strong> <code>__init__</code>. Er wird von Python <strong>automatisch aufgerufen</strong>, sobald ein neues Objekt erstellt wird!
Die Lösung heißt <strong>Konstruktor</strong>: Die spezielle Methode <code>__init__</code>. Sie wird von Python <strong>automatisch aufgerufen</strong>, genau in dem Moment, in dem du ein Objekt erzeugst!
</p>
<div class="box box-analogie">
<div class="box-title">🏗️ Die Geburtsurkunde-Analogie:</div>
Wenn ein neues Objekt "geboren" wird, muss es sofort seine grundlegenden Daten erhalten (Name, Startwert). <code>__init__</code> ist wie das Ausfüllen des Datenblattes bei der Geburt – danach ist das Objekt sofort einsatzbereit!
</div>
</section>
<!-- self Erklärung -->
<!-- 2. Vollständiges Beispiel: Smartphone -->
<section class="card">
<h2>2. Was bedeutet <code>self</code>?</h2>
<h2>2. 📱 Vollständiges Beispiel: Die Smartphone-Klasse</h2>
<p>
Das Wörtchen <code>self</code> steht auf Deutsch für <strong>"ich selbst"</strong> bzw. <strong>"dieses konkrete Objekt hier"</strong>.
</p>
<p>Schau dir an, wie eine vollständige Klasse mit Konstruktor und Methoden in der Praxis aussieht:</p>
<div class="code-container">
<div class="code-header">
@ -64,44 +57,98 @@
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python</span>
<span>Python (Komplettes Beispiel: smartphone.py)</span>
</div>
<pre><span class="kw">class</span> <span class="fn">Bankkonto</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">inhaber</span>, <span class="var">kontostand</span>=<span class="num">0.0</span>):
<span class="var">self</span>.<span class="attr">inhaber</span> = <span class="var">inhaber</span> <span class="cm"># Speichere 'inhaber' im Attribut DIESES Objekts</span>
<span class="var">self</span>.<span class="attr">kontostand</span> = <span class="var">kontostand</span> <span class="cm"># Speichere 'kontostand' in MEINEM Speicher</span>
<pre><span class="cm"># 1. Die vollständige Klasse definieren:</span>
<span class="kw">class</span> <span class="fn">Smartphone</span>:
<span class="cm"># Der Konstruktor wird automatisch beim Erstellen aufgerufen:</span>
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">modell</span>, <span class="var">speicher_gb</span>, <span class="var">akku</span>=<span class="num">100</span>):
<span class="var">self</span>.<span class="attr">modell</span> = <span class="var">modell</span> <span class="cm"># z.B. "iPhone 15"</span>
<span class="var">self</span>.<span class="attr">speicher_gb</span> = <span class="var">speicher_gb</span> <span class="cm"># z.B. 128</span>
<span class="var">self</span>.<span class="attr">akku</span> = <span class="var">akku</span> <span class="cm"># Standardwert ist 100%</span>
<span class="cm"># Verwendung:</span>
<span class="var">konto_anna</span> = <span class="fn">Bankkonto</span>(<span class="str">"Anna"</span>, <span class="num">50.0</span>)
<span class="var">konto_ben</span> = <span class="fn">Bankkonto</span>(<span class="str">"Ben"</span>) <span class="cm"># Verwendet den Standardwert 0.0</span></pre>
<span class="cm"># Eine Methode, die den Akkustand verringert:</span>
<span class="kw">def</span> <span class="fn">benutzen</span>(<span class="var">self</span>, <span class="var">minuten</span>):
<span class="var">verbrauch</span> = <span class="var">minuten</span> * <span class="num">0.5</span>
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">akku</span> >= <span class="var">verbrauch</span>:
<span class="var">self</span>.<span class="attr">akku</span> -= <span class="var">verbrauch</span>
<span class="kw">return</span> <span class="str">f"{self.modell}: {minuten} Min. genutzt. Akku: {self.akku:.0f}%"</span>
<span class="kw">else</span>:
<span class="var">self</span>.<span class="attr">akku</span> = <span class="num">0</span>
<span class="kw">return</span> <span class="str">f"{self.modell}: Akku ist leer!"</span>
<span class="cm"># Eine Methode zum Aufladen:</span>
<span class="kw">def</span> <span class="fn">aufladen</span>(<span class="var">self</span>):
<span class="var">self</span>.<span class="attr">akku</span> = <span class="num">100</span>
<span class="kw">return</span> <span class="str">f"{self.modell} ist wieder voll aufgeladen (100%)!"</span>
<span class="cm"># ==============================================================================</span>
<span class="cm"># Jetzt verwenden wir die Smartphone-Klasse:</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="cm"># Handy 1 erstellen (nutzt Standard-Akku 100%):</span>
<span class="var">mein_handy</span> = <span class="fn">Smartphone</span>(<span class="str">"iPhone 15"</span>, <span class="num">256</span>)
<span class="cm"># Handy 2 erstellen (mit 40% Start-Akku):</span>
<span class="var">altes_handy</span> = <span class="fn">Smartphone</span>(<span class="str">"Galaxy S10"</span>, <span class="num">64</span>, <span class="var">akku</span>=<span class="num">40</span>)
<span class="fn">print</span>(<span class="var">mein_handy</span>.<span class="fn">benutzen</span>(<span class="num">30</span>)) <span class="cm"># Verbraucht 15% -> 85% Rest</span>
<span class="fn">print</span>(<span class="var">altes_handy</span>.<span class="fn">benutzen</span>(<span class="num">90</span>)) <span class="cm"># Akku wird leer!</span>
<span class="fn">print</span>(<span class="var">altes_handy</span>.<span class="fn">aufladen</span>()) <span class="cm"># Wieder 100%</span></pre>
</div>
</section>
<!-- 3. Was bedeutet self im Detail? -->
<section class="card">
<h2>3. Was bedeutet <code>self</code> ganz genau?</h2>
<p>
Das Wörtchen <code>self</code> steht für <strong>"dieses konkrete Objekt hier"</strong>.
</p>
<div class="box box-analogie">
<div class="box-title">🪞 Das Namensschild-Prinzip:</div>
Wenn du <code>mein_handy.benutzen(30)</code> aufrufst, übergibt Python im Hintergrund automatisch <code>mein_handy</code> als erstes Argument <code>self</code>.
<br><br>
<code>self.akku -= verbrauch</code> bedeutet: <em>"Ziehe den Verbrauch vom Akku DIESES Handys ab – nicht von allen anderen Handys auf der Welt!"</em>
</div>
<div class="box box-tipp">
<div class="box-title">💡 Warum <code>self.inhaber = inhaber</code>?</div>
Links vom Gleichheitszeichen steht <code>self.inhaber</code> – das ist die Variable, die <strong>am Objekt dauerhaft gespeichert</strong> bleibt. Rechts steht <code>inhaber</code> – das ist nur der temporäre Übergabeparameter der Funktion.
<ul>
<li><strong>Links (<code>self.inhaber</code>):</strong> Das Attribut, das fest am Objekt im Arbeitsspeicher abgespeichert wird.</li>
<li><strong>Rechts (<code>inhaber</code>):</strong> Der Wert, den jemand beim Aufruf in die Klammern übergeben hat.</li>
</ul>
</div>
</section>
<!-- Stolperfallen -->
<!-- 4. Stolperfallen -->
<section class="card">
<h2>3. Häufige Stolperfallen beim Konstruktor</h2>
<h2>4. ⚠️ Häufige Fehler beim Konstruktor</h2>
<div class="box box-warning">
<div class="box-title">⚠️ Fehler 1: Doppel-Unterstrich vs. Einzel-Unterstrich</div>
Es heißt <code>__init__</code> mit <strong>zwei Unterstrichen</strong> davor und danach (Dunder), NICHT <code>_init_</code>! Wenn du nur einen Unterstrich schreibst, ignoriert Python die Methode einfach.
<div class="box-title">1. Tippfehler bei den Unterstrichen:</div>
<code>def __init__(self):</code> &nbsp;&check; (2 Unterstriche vorne, 2 hinten: Dunder!)<br>
<code>def _init_(self):</code> &nbsp;&cross; (Falsch! Python ruft die Methode nicht auf!)
</div>
<div class="box box-danger">
<div class="box-title">⚠️ Fehler 2: <code>self</code> im Methodenkopf vergessen</div>
Jede Methode in einer Klasse <strong>muss</strong> als allerersten Parameter <code>self</code> haben:
<br><code>def einzahlen(self, betrag):</code> &nbsp;&check;
<br><code>def einzahlen(betrag):</code> &nbsp;&cross; (Führt zu <code>TypeError</code>!)
<div class="box-title">2. 'self' im Methodenkopf vergessen:</div>
<code>def einzahlen(self, betrag):</code> &nbsp;&check;<br>
<code>def einzahlen(betrag):</code> &nbsp;&cross; (Führt zu <code>TypeError: takes 1 positional argument but 2 were given</code>)
</div>
<div class="box box-warning">
<div class="box-title">3. Falsche Zuweisungsrichtung:</div>
<code>self.kontostand = kontostand</code> &nbsp;&check;<br>
<code>kontostand = self.kontostand</code> &nbsp;&cross; (Überschreibt den Parameter, speichert nichts am Objekt!)
</div>
</section>
<!-- Aufgaben -->
<!-- 5. Aufgaben -->
<section class="card">
<h2>4. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>5. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<p>Öffne die Datei <code>02_init_und_self/aufgabe.py</code>:</p>
@ -135,7 +182,7 @@
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>Tipp zu TODO 3 (Auszahlen mit Absicherung)</summary>
<summary>🔍 Tipp zu TODO 3 (Auszahlen mit Absicherung)</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="kw">def</span> <span class="fn">auszahlen</span>(<span class="var">self</span>, <span class="var">betrag</span>):
@ -148,9 +195,9 @@
</details>
</section>
<!-- Testen & Footer Navigation -->
<!-- 6. Testen & Footer Navigation -->
<section class="card">
<h2>5. Lösung überprüfen</h2>
<h2>6. 🧪 Lösung überprüfen</h2>
<p>Führe im Terminal im Ordner <code>02_init_und_self</code> folgenden Befehl aus:</p>
<div class="code-container">
<div class="code-header">

View file

@ -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

View file

@ -19,20 +19,35 @@
</nav>
<div class="header-badge">Kapitel 03</div>
<h1>Methoden &amp; Verhalten: Wenn Objekte lebendig werden ⚔️</h1>
<p>Lass Objekte aktiv handeln und miteinander interagieren in einem rundenbasierten RPG-Heldenduell.</p>
<p>Lass Objekte aktiv handeln und miteinander interagieren anhand eines vollständigen Rennspiel- &amp; Duell-Beispiels.</p>
</div>
</header>
<main class="container">
<!-- Theorie Card -->
<!-- 1. Was sind Methoden -->
<section class="card">
<h2>1. Was sind Methoden?</h2>
<p>
Bisher haben unsere Klassen vor allem Daten gespeichert. Aber in der objektorientierten Programmierung haben Objekte auch <strong>Verhalten</strong>. Funktionen, die zu einer Klasse gehören, nennt man <strong>Methoden</strong>.
Bisher haben unsere Klassen vor allem Daten gespeichert. Aber in der echten Programmierung haben Objekte auch <strong>Verhalten</strong> (sie können etwas <em>tun</em>). Funktionen, die innerhalb einer Klasse stehen, nennt man <strong>Methoden</strong>.
</p>
<div class="box box-tipp">
<div class="box-title">💡 Der Unterschied zwischen Funktion und Methode:</div>
<ul>
<li>Eine <strong>Funktion</strong> steht frei im Code: <code>berechne_summe(a, b)</code></li>
<li>Eine <strong>Methode</strong> gehört zu einem Objekt und wird mit Punkt aufgerufen: <code>mein_held.angreifen(gegner)</code></li>
</ul>
</div>
</section>
<!-- 2. Vollständiges Beispiel: Rennauto -->
<section class="card">
<h2>2. 🏎️ Vollständiges Beispiel: Die Rennauto-Klasse</h2>
<p>Hier siehst du eine vollständige Klasse mit Konstruktor, mehreren Methoden, Wertebegrenzung (Tankinhalt) und einer Renn-Simulation:</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
@ -40,44 +55,76 @@
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python</span>
<span>Python (Komplettes Beispiel: rennauto.py)</span>
</div>
<pre><span class="kw">class</span> <span class="fn">Zauberer</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>, <span class="var">mana</span>=<span class="num">50</span>):
<span class="var">self</span>.<span class="attr">name</span> = <span class="var">name</span>
<span class="var">self</span>.<span class="attr">mana</span> = <span class="var">mana</span>
<pre><span class="kw">class</span> <span class="fn">Rennauto</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">fahrer</span>, <span class="var">speed</span>, <span class="var">tank</span>=<span class="num">50</span>):
<span class="var">self</span>.<span class="attr">fahrer</span> = <span class="var">fahrer</span>
<span class="var">self</span>.<span class="attr">speed</span> = <span class="var">speed</span> <span class="cm"># z.B. 220 km/h</span>
<span class="var">self</span>.<span class="attr">tank</span> = <span class="var">tank</span> <span class="cm"># Aktueller Tank in Litern</span>
<span class="var">self</span>.<span class="attr">max_tank</span> = <span class="var">tank</span> <span class="cm"># Maximales Tankvolumen</span>
<span class="var">self</span>.<span class="attr">gefahrene_km</span> = <span class="num">0</span>
<span class="cm"># Eine Methode gehört dem Zauberer:</span>
<span class="kw">def</span> <span class="fn">zauberspruch_wirken</span>(<span class="var">self</span>, <span class="var">kosten</span>):
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">mana</span> >= <span class="var">kosten</span>:
<span class="var">self</span>.<span class="attr">mana</span> -= <span class="var">kosten</span>
<span class="kw">return</span> <span class="kw">True</span>
<span class="kw">return</span> <span class="kw">False</span></pre>
<span class="cm"># Methode 1: Fahren (verbraucht Benzin)</span>
<span class="kw">def</span> <span class="fn">fahren</span>(<span class="var">self</span>, <span class="var">km</span>):
<span class="var">verbrauch</span> = <span class="var">km</span> * <span class="num">0.2</span> <span class="cm"># 0.2 Liter pro km</span>
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">tank</span> >= <span class="var">verbrauch</span>:
<span class="var">self</span>.<span class="attr">tank</span> -= <span class="var">verbrauch</span>
<span class="var">self</span>.<span class="attr">gefahrene_km</span> += <span class="var">km</span>
<span class="kw">return</span> <span class="str">f"{self.fahrer} fährt {km} km (Tank: {self.tank:.1f}L übrig)"</span>
<span class="kw">else</span>:
<span class="kw">return</span> <span class="str">f"{self.fahrer} hat nicht genug Sprit für {km} km!"</span>
<span class="cm"># Methode 2: Tanken (nicht über max_tank)</span>
<span class="kw">def</span> <span class="fn">tanken</span>(<span class="var">self</span>, <span class="var">liter</span>):
<span class="var">freier_platz</span> = <span class="var">self</span>.<span class="attr">max_tank</span> - <span class="var">self</span>.<span class="attr">tank</span>
<span class="var">getankt</span> = <span class="fn">min</span>(<span class="var">freier_platz</span>, <span class="var">liter</span>)
<span class="var">self</span>.<span class="attr">tank</span> += <span class="var">getankt</span>
<span class="kw">return</span> <span class="str">f"{self.fahrer} tankt {getankt:.1f} Liter nach (Tank: {self.tank:.1f}/{self.max_tank}L)"</span>
<span class="cm"># Methode 3: Interaktion mit einem anderen Auto</span>
<span class="kw">def</span> <span class="fn">duell_gegen</span>(<span class="var">self</span>, <span class="var">gegner_auto</span>):
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">speed</span> > <span class="var">gegner_auto</span>.<span class="attr">speed</span>:
<span class="kw">return</span> <span class="str">f"{self.fahrer} überholt {gegner_auto.fahrer} mit Leichtigkeit!"</span>
<span class="kw">elif</span> <span class="var">self</span>.<span class="attr">speed</span> &lt; <span class="var">gegner_auto</span>.<span class="attr">speed</span>:
<span class="kw">return</span> <span class="str">f"{gegner_auto.fahrer} zieht an {self.fahrer} vorbei!"</span>
<span class="kw">else</span>:
<span class="kw">return</span> <span class="str">f"{self.fahrer} und {gegner_auto.fahrer} sind genau gleich schnell!"</span>
<span class="cm"># Ausprobieren:</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="var">auto1</span> = <span class="fn">Rennauto</span>(<span class="str">"Max"</span>, <span class="var">speed</span>=<span class="num">240</span>, <span class="var">tank</span>=<span class="num">40</span>)
<span class="var">auto2</span> = <span class="fn">Rennauto</span>(<span class="str">"Lewis"</span>, <span class="var">speed</span>=<span class="num">235</span>, <span class="var">tank</span>=<span class="num">50</span>)
<span class="fn">print</span>(<span class="var">auto1</span>.<span class="fn">fahren</span>(<span class="num">100</span>)) <span class="cm"># Verbraucht 20 Liter -> 20L übrig</span>
<span class="fn">print</span>(<span class="var">auto1</span>.<span class="fn">duell_gegen</span>(<span class="var">auto2</span>)) <span class="cm"># Max ist schneller als Lewis!</span>
<span class="fn">print</span>(<span class="var">auto1</span>.<span class="fn">tanken</span>(<span class="num">30</span>)) <span class="cm"># Tankt bis max 40L auf</span></pre>
</div>
</section>
<!-- Interaktion zwischen Objekten -->
<!-- 3. Interaktion zwischen Objekten -->
<section class="card">
<h2>2. Wenn zwei Objekte miteinander interagieren</h2>
<h2>3. 🤝 Interaktion: Ein Objekt übergibt sich an ein anderes</h2>
<p>
Besonders spannend wird es, wenn eine Methode eines Objekts ein <strong>anderes Objekt als Parameter</strong> bekommt (z.B. <code>ritter.angreifen(drache)</code>).
In der Methode <code>angreifen(self, gegner)</code> übergibst du das gegnerische Held-Objekt als Parameter:
</p>
<div class="box box-analogie">
<div class="box-title">🤝 Die Duell-Analogie:</div>
In <code>angreifen(self, gegner)</code> ist <code>self</code> der Angreifer (z.B. Arthur) und <code>gegner</code> ist das Ziel (z.B. der Drache). Arthur ruft <code>gegner.schaden_erleiden(self.angriffskraft)</code> auf. So beeinflussen sich die Objekte gegenseitig!
</div>
<div class="box box-warning">
<div class="box-title">⚠️ Wichtig: Logische Grenzen einhalten (Clamping)!</div>
Lebenspunkte dürfen niemals unter <code>0</code> fallen (ein besiegter Held hat 0 HP, nicht -15 HP) und bei Heilung niemals über <code>max_leben</code> steigen.
<div class="box-title">⚔️ Wie das Helden-Duell funktioniert:</div>
<code>ritter.angreifen(drache)</code>
<br><br>
1. <code>self</code> ist der Ritter (mit <code>self.angriffskraft</code>).<br>
2. <code>gegner</code> ist der Drache.<br>
3. Der Ritter ruft: <code>gegner.schaden_erleiden(self.angriffskraft)</code> auf!<br>
4. Der Drache verliert Leben und prüft, ob er noch lebt.
</div>
</section>
<!-- Aufgaben Card -->
<!-- 4. Aufgaben Card -->
<section class="card">
<h2>3. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>4. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<ul class="task-list">
<li class="task-item">
@ -89,25 +136,25 @@
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t3_2">
<label for="t3_2" class="task-label">
<strong>TODO 2:</strong> Methode <code>schaden_erleiden(self, schaden)</code>: Zieht Schaden ab. Fällt das Leben auf/unter 0 -> setze <code>leben = 0</code> und <code>ist_am_leben = False</code>.
<strong>TODO 2:</strong> <code>schaden_erleiden(self, schaden)</code>: Wenn <code>leben &lt;= 0</code> wird -> <code>leben = 0</code> und <code>ist_am_leben = False</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t3_3">
<label for="t3_3" class="task-label">
<strong>TODO 3:</strong> Methode <code>heilen(self, heilung)</code>: Erhöht Leben maximal bis <code>max_leben</code> (nur wenn noch am Leben).
<strong>TODO 3:</strong> <code>heilen(self, heilung)</code>: Erhöht Leben maximal bis <code>max_leben</code> (nur wenn noch am Leben).
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t3_4">
<label for="t3_4" class="task-label">
<strong>TODO 4:</strong> Methode <code>angreifen(self, gegner)</code>: Wenn beide lebendig sind, rufe <code>gegner.schaden_erleiden(self.angriffskraft)</code> auf.
<strong>TODO 4:</strong> <code>angreifen(self, gegner)</code>: Ruft <code>gegner.schaden_erleiden(self.angriffskraft)</code> auf (nur wenn beide leben).
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t3_5">
<label for="t3_5" class="task-label">
<strong>TODO 5:</strong> Methode <code>status_text(self)</code>: Gibt formatierten Status zurück.
<strong>TODO 5:</strong> <code>status_text(self)</code>: Gibt formatierten Status zurück.
</label>
</li>
</ul>
@ -115,23 +162,22 @@
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>Tipp zu TODO 3 (Heilung begrenzen)</summary>
<summary>🔍 Tipp zu TODO 4 (Angriff)</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="kw">def</span> <span class="fn">heilen</span>(<span class="var">self</span>, <span class="var">heilung</span>):
<span class="kw">if</span> <span class="kw">not</span> <span class="var">self</span>.<span class="attr">ist_am_leben</span> <span class="kw">or</span> <span class="var">heilung</span> &lt;= <span class="num">0</span>:
<span class="kw">return</span> <span class="num">0</span>
<span class="var">alter_wert</span> = <span class="var">self</span>.<span class="attr">leben</span>
<span class="var">self</span>.<span class="attr">leben</span> = <span class="fn">min</span>(<span class="var">self</span>.<span class="attr">max_leben</span>, <span class="var">self</span>.<span class="attr">leben</span> + <span class="var">heilung</span>)
<span class="kw">return</span> <span class="var">self</span>.<span class="attr">leben</span> - <span class="var">alter_wert</span> <span class="cm"># Wie viel wurde wirklich geheilt?</span></pre>
<pre><span class="kw">def</span> <span class="fn">angreifen</span>(<span class="var">self</span>, <span class="var">gegner</span>):
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">ist_am_leben</span> <span class="kw">and</span> <span class="var">gegner</span>.<span class="attr">ist_am_leben</span>:
<span class="var">gegner</span>.<span class="fn">schaden_erleiden</span>(<span class="var">self</span>.<span class="attr">angriffskraft</span>)
<span class="kw">return</span> <span class="kw">True</span>
<span class="kw">return</span> <span class="kw">False</span></pre>
</div>
</div>
</details>
</section>
<!-- Testen & Footer Navigation -->
<!-- 5. Testen & Navigation -->
<section class="card">
<h2>4. Lösung überprüfen</h2>
<h2>5. 🧪 Lösung überprüfen</h2>
<p>Führe im Terminal im Ordner <code>03_methoden_und_verhalten</code> folgenden Befehl aus:</p>
<div class="code-container">
<div class="code-header">

View file

@ -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())
```
---

View file

@ -19,18 +19,18 @@
</nav>
<div class="header-badge">Kapitel 04</div>
<h1>Schöne Ausgaben mit <code>__str__</code> &amp; Objektlisten 🧾</h1>
<p>Lerne, wie du bestimmst, was beim <code>print(objekt)</code> erscheint und wie Objekte andere Objekte in Listen verwalten.</p>
<p>Lerne anhand eines Pizzeria-Beispiels, wie du <code>print(objekt)</code> formatierst und Objekte in Listen sammelst.</p>
</div>
</header>
<main class="container">
<!-- Theorie Card -->
<!-- 1. Das Problem mit Standard print -->
<section class="card">
<h2>1. Warum sieht <code>print(objekt)</code> standardmäßig so hässlich aus?</h2>
<h2>1. Warum sieht <code>print(objekt)</code> standardmäßig so kryptisch aus?</h2>
<p>
Wenn du versuchst, ein Objekt ohne Dunder-Methode zu drucken:
Wenn du versuchst, ein Objekt ohne die Dunder-Methode <code>__str__</code> auszudrucken:
</p>
<div class="code-container">
@ -39,13 +39,20 @@
</div>
<p>
Python weiß ohne deine Hilfe nicht, wie du dein Objekt darstellen möchtest.
Python weiß nicht, welche Attribute für einen Menschen interessant sind.
</p>
<div class="box box-tipp">
<div class="box-title">✨ Die Magie von <code>__str__</code>:</div>
Sobald du in deiner Klasse eine Methode <code>def __str__(self):</code> definierst, ruft Python diese automatisch auf, wann immer das Objekt zu Text umgewandelt wird (bei <code>print()</code>, <code>str()</code> oder in f-Strings)!
Sobald du in deiner Klasse die Methode <code>def __str__(self):</code> definierst, ruft Python diese automatisch auf, sobald das Objekt in Text umgewandelt werden soll (bei <code>print()</code>, <code>str()</code> oder in f-Strings <code>f"{objekt}"</code>)!
</div>
</section>
<!-- 2. Vollständiges Beispiel: Pizza & Pizzeria -->
<section class="card">
<h2>2. 🍕 Vollständiges Beispiel: Pizza &amp; Pizzeria-Bestellung</h2>
<p>Hier siehst du zwei vollständige Klassen, die zusammenarbeiten: <code>Pizza</code> (mit <code>__str__</code>) und <code>Bestellung</code> (die eine Liste von Pizzen verwaltet):</p>
<div class="code-container">
<div class="code-header">
@ -54,38 +61,81 @@
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python</span>
<span>Python (Komplettes Beispiel: pizzeria.py)</span>
</div>
<pre><span class="kw">class</span> <span class="fn">Buch</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">titel</span>, <span class="var">autor</span>):
<span class="var">self</span>.<span class="attr">titel</span> = <span class="var">titel</span>
<span class="var">self</span>.<span class="attr">autor</span> = <span class="var">autor</span>
<pre><span class="cm"># ==============================================================================</span>
<span class="cm"># KLASSE 1: Einzelne Pizza mit schöner __str__ Ausgabe</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">class</span> <span class="fn">Pizza</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>, <span class="var">preis</span>, <span class="var">extra_kaese</span>=<span class="kw">False</span>):
<span class="var">self</span>.<span class="attr">name</span> = <span class="var">name</span>
<span class="var">self</span>.<span class="attr">preis</span> = <span class="var">preis</span>
<span class="var">self</span>.<span class="attr">extra_kaese</span> = <span class="var">extra_kaese</span>
<span class="kw">if</span> <span class="var">extra_kaese</span>:
<span class="var">self</span>.<span class="attr">preis</span> += <span class="num">1.50</span> <span class="cm"># Extra Käse kostet 1.50€ mehr</span>
<span class="cm"># Diese Methode bestimmt, wie die Pizza als Text aussieht:</span>
<span class="kw">def</span> <span class="fn">__str__</span>(<span class="var">self</span>):
<span class="kw">return</span> <span class="str">f"'{self.titel}' von {self.autor}"</span> <span class="cm"># MUSS ein String sein!</span>
<span class="var">kaese_hinweis</span> = <span class="str">" (mit Extra-Käse 🧀)"</span> <span class="kw">if</span> <span class="var">self</span>.<span class="attr">extra_kaese</span> <span class="kw">else</span> <span class="str">""</span>
<span class="kw">return</span> <span class="str">f"Pizza {self.name}{kaese_hinweis} - {self.preis:.2f} €"</span>
<span class="var">mein_buch</span> = <span class="fn">Buch</span>(<span class="str">"Harry Potter"</span>, <span class="str">"J.K. Rowling"</span>)
<span class="fn">print</span>(<span class="var">mein_buch</span>) <span class="cm"># Ausgabe: 'Harry Potter' von J.K. Rowling</span></pre>
<span class="cm"># ==============================================================================</span>
<span class="cm"># KLASSE 2: Bestellung verwaltet eine Liste von Pizzen</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">class</span> <span class="fn">Bestellung</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">kunden_name</span>):
<span class="var">self</span>.<span class="attr">kunden_name</span> = <span class="var">kunden_name</span>
<span class="var">self</span>.<span class="attr">pizzen</span> = [] <span class="cm"># Startet mit einer leeren Liste</span>
<span class="kw">def</span> <span class="fn">pizza_hinzufuegen</span>(<span class="var">self</span>, <span class="var">pizza</span>):
<span class="var">self</span>.<span class="attr">pizzen</span>.<span class="fn">append</span>(<span class="var">pizza</span>)
<span class="kw">def</span> <span class="fn">gesamtpreis</span>(<span class="var">self</span>):
<span class="kw">return</span> <span class="fn">sum</span>(<span class="var">p</span>.<span class="attr">preis</span> <span class="kw">for</span> <span class="var">p</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">pizzen</span>)
<span class="kw">def</span> <span class="fn">rechnung_drucken</span>(<span class="var">self</span>):
<span class="var">zeilen</span> = [<span class="str">f"=== RECHNUNG FÜR {self.kunden_name.upper()} ==="</span>]
<span class="kw">for</span> <span class="var">p</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">pizzen</span>:
<span class="var">zeilen</span>.<span class="fn">append</span>(<span class="str">f"- {p}"</span>) <span class="cm"># Hier wird automatisch p.__str__() aufgerufen!</span>
<span class="var">zeilen</span>.<span class="fn">append</span>(<span class="str">"--------------------------------"</span>)
<span class="var">zeilen</span>.<span class="fn">append</span>(<span class="str">f"Gesamtsumme: {self.gesamtpreis():.2f} €"</span>)
<span class="kw">return</span> <span class="str">"\n"</span>.<span class="fn">join</span>(<span class="var">zeilen</span>)
<span class="cm"># Ausprobieren:</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="var">bestellung</span> = <span class="fn">Bestellung</span>(<span class="str">"Lisa"</span>)
<span class="var">p1</span> = <span class="fn">Pizza</span>(<span class="str">"Margherita"</span>, <span class="num">8.50</span>)
<span class="var">p2</span> = <span class="fn">Pizza</span>(<span class="str">"Salami"</span>, <span class="num">9.50</span>, <span class="var">extra_kaese</span>=<span class="kw">True</span>)
<span class="var">bestellung</span>.<span class="fn">pizza_hinzufuegen</span>(<span class="var">p1</span>)
<span class="var">bestellung</span>.<span class="fn">pizza_hinzufuegen</span>(<span class="var">p2</span>)
<span class="fn">print</span>(<span class="var">bestellung</span>.<span class="fn">rechnung_drucken</span>())</pre>
</div>
</section>
<!-- Objektlisten Card -->
<!-- 3. Stolperfallen -->
<section class="card">
<h2>2. Objekte in Listen verwalten</h2>
<h2>3. ⚠️ Wichtig bei <code>__str__</code></h2>
<p>
Eine Klasse kann als Attribut eine <strong>Liste von anderen Objekten</strong> haben:
</p>
<div class="box box-danger">
<div class="box-title">1. Immer 'return', niemals 'print'!</div>
<code>def __str__(self): return f"..."</code> &nbsp;&check;<br>
<code>def __str__(self): print(f"...")</code> &nbsp;&cross; (Falsch! <code>__str__</code> MUSS einen String mit <code>return</code> zurückgeben!)
</div>
<div class="box box-analogie">
<div class="box-title">🛒 Der Warenkorb:</div>
Ein <code>Warenkorb</code> besitzt eine Liste <code>self.artikel_liste = []</code>. Wenn du einen <code>Artikel</code> hinzufügst, landet das ganze Artikel-Objekt in der Liste!
<div class="box box-warning">
<div class="box-title">2. Rückgabewert muss zwingend ein String sein:</div>
Wenn du eine Zahl zurückgibst (z.B. <code>return self.preis</code>), stürzt Python ab mit <code>TypeError: __str__ returned non-string</code>. Nutze immer f-Strings <code>f"{self.preis}"</code> oder <code>str(...)</code>.
</div>
</section>
<!-- Aufgaben Card -->
<!-- 4. Aufgaben Card -->
<section class="card">
<h2>3. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>4. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<ul class="task-list">
<li class="task-item">
@ -103,7 +153,7 @@
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t4_3">
<label for="t4_3" class="task-label">
<strong>TODO 3:</strong> <code>Artikel.__str__(self)</code> -> z.B. <code>"2x Milch (je 1.29 €) = 2.58 €"</code>.
<strong>TODO 3:</strong> <code>Artikel.__str__(self)</code> -> <code>"{anzahl}x {name} (je {preis:.2f} €) = {gesamtpreis:.2f} €"</code>.
</label>
</li>
<li class="task-item">
@ -117,7 +167,7 @@
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>Tipp zu TODO 7 (Kassenzettel zusammensetzen)</summary>
<summary>🔍 Tipp zu TODO 7 (Kassenzettel zusammensetzen)</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="kw">def</span> <span class="fn">bon_text</span>(<span class="var">self</span>):
@ -132,9 +182,9 @@
</details>
</section>
<!-- Testen & Footer Navigation -->
<!-- 5. Testen & Navigation -->
<section class="card">
<h2>4. Lösung überprüfen</h2>
<h2>5. 🧪 Lösung überprüfen</h2>
<p>Führe im Terminal im Ordner <code>04_str_und_darstellung</code> folgenden Befehl aus:</p>
<div class="code-container">
<div class="code-header">

View file

@ -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

View file

@ -25,60 +25,111 @@
<main class="container">
<!-- Theorie Card -->
<!-- 1. Was ist Komposition -->
<section class="card">
<h2>1. Was ist Komposition?</h2>
<p>
In großen Anwendungen (wie Spotify, Netflix oder Videospielen) arbeiten viele Klassen zusammen. Wenn eine Klasse Instanzen einer anderen Klasse beinhaltet, nennt man das <strong>Komposition</strong> (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 <strong>Komposition</strong> (oder *"hat-ein"-Beziehung*):
</p>
<ul style="margin-left: 20px; margin-bottom: 15px;">
<li>Eine <strong>Schulklasse</strong> <em>hat</em> viele <strong>Schüler</strong>.</li>
<li>Eine <strong>Playlist</strong> <em>hat</em> viele <strong>Songs</strong>.</li>
<li>Ein <strong>Kino</strong> <em>hat</em> viele <strong>Säle</strong> und <strong>Filme</strong>.</li>
<li>Ein <strong>Kino</strong> <em>hat</em> viele <strong>Säle</strong>.</li>
</ul>
<div class="box box-analogie">
<div class="box-title">🎧 Die Spotify-Analogie:</div>
Ein <code>Song</code> speichert seinen Titel, den Künstler und die Länge in Sekunden. Die <code>Playlist</code> kümmert sich um die Gesamtübersicht: Wie viele Songs gibt es? Wie lange dauert die Playlist insgesamt? Gibt es Lieder von Taylor Swift?
</div>
</section>
<!-- Filter & Formatierung Card -->
<!-- 2. Vollständiges Beispiel: Notenmanager -->
<section class="card">
<h2>2. Nützliche Python-Kniffe</h2>
<h2>2. 🎒 Vollständiges Beispiel: Schüler &amp; Schulklasse Notenmanager</h2>
<h3>⏱️ Sekunden in "MM:SS" umrechnen</h3>
<p>
Mit Ganzzahldivision <code>//</code> und Modulo <code>%</code> rechnen wir Sekunden in Minuten um:
</p>
<p>Hier siehst du ein vollständiges Beispiel aus dem Schulalltag: Die Klasse <code>Schueler</code> speichert Name und Note. Die Klasse <code>Schulklasse</code> verwaltet alle Schüler, berechnet den Notendurchschnitt und sucht die Klassenbesten:</p>
<div class="code-container">
<div class="code-header">
<span>Python</span>
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Komplettes Beispiel: schulklasse.py)</span>
</div>
<pre><span class="var">gesamt_sekunden</span> = <span class="num">215</span>
<span class="var">minuten</span> = <span class="var">gesamt_sekunden</span> // <span class="num">60</span> <span class="cm"># 3 Minuten</span>
<span class="var">sekunden</span> = <span class="var">gesamt_sekunden</span> % <span class="num">60</span> <span class="cm"># 35 Restsekunden</span>
<pre><span class="cm"># ==============================================================================</span>
<span class="cm"># KLASSE 1: Ein einzelner Schüler</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">class</span> <span class="fn">Schueler</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>, <span class="var">note</span>):
<span class="var">self</span>.<span class="attr">name</span> = <span class="var">name</span>
<span class="var">self</span>.<span class="attr">note</span> = <span class="fn">float</span>(<span class="var">note</span>)
<span class="cm"># :02d sorgt für zweistellige Zahlen mit führender Null (z.B. 03:05 statt 3:5):</span>
<span class="var">zeit_text</span> = <span class="str">f"{minuten:02d}:{sekunden:02d}"</span> <span class="cm"># "03:35"</span></pre>
<span class="kw">def</span> <span class="fn">__str__</span>(<span class="var">self</span>):
<span class="kw">return</span> <span class="str">f"{self.name} (Note: {self.note:.1f})"</span>
<span class="cm"># ==============================================================================</span>
<span class="cm"># KLASSE 2: Die Schulklasse verwaltet viele Schüler-Objekte</span>
<span class="cm"># ==============================================================================</span>
<span class="kw">class</span> <span class="fn">Schulklasse</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">klassen_name</span>):
<span class="var">self</span>.<span class="attr">klassen_name</span> = <span class="var">klassen_name</span>
<span class="var">self</span>.<span class="attr">schueler_liste</span> = []
<span class="kw">def</span> <span class="fn">hinzufuegen</span>(<span class="var">self</span>, <span class="var">schueler</span>):
<span class="var">self</span>.<span class="attr">schueler_liste</span>.<span class="fn">append</span>(<span class="var">schueler</span>)
<span class="kw">def</span> <span class="fn">notendurchschnitt</span>(<span class="var">self</span>):
<span class="kw">if</span> <span class="kw">not</span> <span class="var">self</span>.<span class="attr">schueler_liste</span>:
<span class="kw">return</span> <span class="num">0.0</span>
<span class="var">summe</span> = <span class="fn">sum</span>(<span class="var">s</span>.<span class="attr">note</span> <span class="kw">for</span> <span class="var">s</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">schueler_liste</span>)
<span class="kw">return</span> <span class="var">summe</span> / <span class="fn">len</span>(<span class="var">self</span>.<span class="attr">schueler_liste</span>)
<span class="kw">def</span> <span class="fn">beste_schueler</span>(<span class="var">self</span>):
<span class="cm"># Findet alle Schüler mit einer 1 (Note &lt;= 1.5)</span>
<span class="kw">return</span> [<span class="var">s</span> <span class="kw">for</span> <span class="var">s</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">schueler_liste</span> <span class="kw">if</span> <span class="var">s</span>.<span class="attr">note</span> &lt;= <span class="num">1.5</span>]
<span class="cm"># Ausprobieren:</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="var">klasse_9a</span> = <span class="fn">Schulklasse</span>(<span class="str">"Klasse 9a"</span>)
<span class="var">s1</span> = <span class="fn">Schueler</span>(<span class="str">"Emma"</span>, <span class="num">1.0</span>)
<span class="var">s2</span> = <span class="fn">Schueler</span>(<span class="str">"Lukas"</span>, <span class="num">2.3</span>)
<span class="var">s3</span> = <span class="fn">Schueler</span>(<span class="str">"Mia"</span>, <span class="num">1.3</span>)
<span class="var">klasse_9a</span>.<span class="fn">hinzufuegen</span>(<span class="var">s1</span>)
<span class="var">klasse_9a</span>.<span class="fn">hinzufuegen</span>(<span class="var">s2</span>)
<span class="var">klasse_9a</span>.<span class="fn">hinzufuegen</span>(<span class="var">s3</span>)
<span class="fn">print</span>(<span class="str">f"Durchschnitt: {klasse_9a.notendurchschnitt():.2f}"</span>) <span class="cm"># 1.53</span>
<span class="fn">print</span>(<span class="str">"\nBeste Schüler:"</span>)
<span class="kw">for</span> <span class="var">einserschueler</span> <span class="kw">in</span> <span class="var">klasse_9a</span>.<span class="fn">beste_schueler</span>():
<span class="fn">print</span>(<span class="str">f"- {einserschueler}"</span>)</pre>
</div>
</section>
<!-- 3. Nützliche Kniffe -->
<section class="card">
<h2>3. Nützliche Kniffe für die Song-Aufgabe</h2>
<h3>⏱️ Sekunden in "MM:SS" umrechnen</h3>
<div class="code-container">
<pre><span class="var">minuten</span> = <span class="var">self</span>.<span class="attr">dauer_sekunden</span> // <span class="num">60</span>
<span class="var">sekunden</span> = <span class="var">self</span>.<span class="attr">dauer_sekunden</span> % <span class="num">60</span>
<span class="kw">return</span> <span class="str">f"{minuten:02d}:{sekunden:02d}"</span> <span class="cm"># z.B. "03:35"</span></pre>
</div>
<h3>🔍 Groß- und Kleinschreibung beim Suchen ignorieren</h3>
<p>
Damit <code>"Taylor Swift"</code> auch gefunden wird, wenn jemand <code>"taylor swift"</code> eingibt, nutzen wir <code>.lower()</code>:
</p>
<div class="code-container">
<pre><span class="kw">if</span> <span class="var">song</span>.<span class="attr">kuenstler</span>.<span class="fn">lower</span>() == <span class="var">gesuchter_kuenstler</span>.<span class="fn">lower</span>():
<pre><span class="kw">if</span> <span class="var">song</span>.<span class="attr">kuenstler</span>.<span class="fn">lower</span>() == <span class="var">kuenstler</span>.<span class="fn">lower</span>():
<span class="var">treffer</span>.<span class="fn">append</span>(<span class="var">song</span>)</pre>
</div>
</section>
<!-- Aufgaben Card -->
<!-- 4. Aufgaben Card -->
<section class="card">
<h2>3. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>4. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<ul class="task-list">
<li class="task-item">
@ -102,7 +153,7 @@
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t5_4">
<label for="t5_4" class="task-label">
<strong>Playlist Suchen &amp; Finden:</strong> <code>finde_songs_von(kuenstler)</code> und <code>laengster_song()</code>.
<strong>Playlist Suchen:</strong> <code>finde_songs_von(kuenstler)</code> und <code>laengster_song()</code>.
</label>
</li>
</ul>
@ -110,7 +161,7 @@
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>Tipp zum längsten Song finden</summary>
<summary>🔍 Tipp zum längsten Song finden</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="kw">def</span> <span class="fn">laengster_song</span>(<span class="var">self</span>):
@ -127,9 +178,9 @@
</details>
</section>
<!-- Testen & Footer Navigation -->
<!-- 5. Testen & Navigation -->
<section class="card">
<h2>4. Lösung überprüfen</h2>
<h2>5. 🧪 Lösung überprüfen</h2>
<p>Führe im Terminal im Ordner <code>05_objekte_kombinieren</code> folgenden Befehl aus:</p>
<div class="code-container">
<div class="code-header">

View file

@ -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!
---

View file

@ -19,73 +19,119 @@
</nav>
<div class="header-badge">Abschlussprojekt</div>
<h1>Dein eigenes Tamagotchi (Virtuelles Haustier) 🥚🐣</h1>
<p>Kombiniere alle Konzepte in einem interaktiven, voll funktionsfähigen Konsolenspiel!</p>
<p>Kombiniere alle gelernten OOP-Konzepte in einem interaktiven, voll funktionsfähigen Konsolenspiel!</p>
</div>
</header>
<main class="container">
<!-- Übersicht Card -->
<!-- 1. Das große Finale -->
<section class="card">
<h2>1. Das große Finale! 🏆</h2>
<p>
Du hast alle Grundlagen gelernt: Klassen definieren, <code>__init__</code> &amp; <code>self</code> nutzen, Methoden schreiben, <code>__str__</code> gestalten und Objekte verwalten.
</p>
<p>
Jetzt bauen wir ein komplettes, lebendiges <strong>Tamagotchi</strong>, das du im Terminal füttern, schlafen legen und mit dem du spielen kannst!
Du hast alle Grundlagen gemeistert: Klassen &amp; Konstruktoren, Methoden, <code>__str__</code> 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!
</p>
</section>
<div class="box box-analogie">
<div class="box-title">🎮 Wie das Spiel funktioniert:</div>
<ul style="margin-left: 20px;">
<li>🍖 <strong>Hunger</strong> (0 bis 100): Steigt mit der Zeit, sinkt beim Füttern. Bei 100 stirbt das Haustier!</li>
<li>💤 <strong>Müdigkeit</strong> (0 bis 100): Steigt bei Aktionen. Bei über 80 weigert es sich zu spielen. Schlafen setzt Müdigkeit auf 0.</li>
<li>💖 <strong>Glück</strong> (0 bis 100): Steigt beim Spielen, sinkt mit der Zeit. Bei 0 stirbt das Haustier vor Einsamkeit.</li>
<li>📅 <strong>Alter</strong>: Bei jedem Schlafen vergeht ein neuer Tag (<code>alter_tage += 1</code>).</li>
</ul>
<!-- 2. Vollständiges Mini-Beispiel: Der Roboter -->
<section class="card">
<h2>2. 🤖 Vollständiges Beispiel: Ein Roboter mit Lebenszyklus</h2>
<p>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:</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Komplettes Beispiel: roboter.py)</span>
</div>
<pre><span class="kw">class</span> <span class="fn">Roboter</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>):
<span class="var">self</span>.<span class="attr">name</span> = <span class="var">name</span>
<span class="var">self</span>.<span class="attr">energie</span> = <span class="num">100</span> <span class="cm"># 100% Start-Energie</span>
<span class="var">self</span>.<span class="attr">ist_aktiv</span> = <span class="kw">True</span>
<span class="cm"># Hilfsmethode, um Werte zwischen 0 und 100 zu halten:</span>
<span class="kw">def</span> <span class="fn">_begrenzen</span>(<span class="var">self</span>, <span class="var">wert</span>):
<span class="kw">return</span> <span class="fn">max</span>(<span class="num">0</span>, <span class="fn">min</span>(<span class="num">100</span>, <span class="var">wert</span>))
<span class="kw">def</span> <span class="fn">arbeiten</span>(<span class="var">self</span>, <span class="var">dauer_stunden</span>):
<span class="kw">if</span> <span class="kw">not</span> <span class="var">self</span>.<span class="attr">ist_aktiv</span>:
<span class="kw">return</span> <span class="str">f"{self.name} ist ausgeschaltet!"</span>
<span class="var">verbrauch</span> = <span class="var">dauer_stunden</span> * <span class="num">20</span>
<span class="var">self</span>.<span class="attr">energie</span> = <span class="var">self</span>.<span class="fn">_begrenzen</span>(<span class="var">self</span>.<span class="attr">energie</span> - <span class="var">verbrauch</span>)
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">energie</span> == <span class="num">0</span>:
<span class="var">self</span>.<span class="attr">ist_aktiv</span> = <span class="kw">False</span>
<span class="kw">return</span> <span class="str">f"{self.name} hat keine Energie mehr und schaltet sich ab!"</span>
<span class="kw">return</span> <span class="str">f"{self.name} hat {dauer_stunden}h gearbeitet. Restenergie: {self.energie}%"</span>
<span class="kw">def</span> <span class="fn">aufladen</span>(<span class="var">self</span>):
<span class="var">self</span>.<span class="attr">energie</span> = <span class="num">100</span>
<span class="var">self</span>.<span class="attr">ist_aktiv</span> = <span class="kw">True</span>
<span class="kw">return</span> <span class="str">f"{self.name} ist wieder voll aufgeladen!"</span>
<span class="kw">def</span> <span class="fn">__str__</span>(<span class="var">self</span>):
<span class="var">status</span> = <span class="str">"Aktiv ⚡"</span> <span class="kw">if</span> <span class="var">self</span>.<span class="attr">ist_aktiv</span> <span class="kw">else</span> <span class="str">"Ausgeschaltet 💤"</span>
<span class="kw">return</span> <span class="str">f"[{self.name}] Energie: {self.energie}% | Status: {status}"</span>
<span class="cm"># Ausprobieren:</span>
<span class="kw">if</span> <span class="var">__name__</span> == <span class="str">"__main__"</span>:
<span class="var">bot</span> = <span class="fn">Roboter</span>(<span class="str">"Wall-E"</span>)
<span class="fn">print</span>(<span class="var">bot</span>)
<span class="fn">print</span>(<span class="var">bot</span>.<span class="fn">arbeiten</span>(<span class="num">3</span>)) <span class="cm"># Verbraucht 60% -> 40% übrig</span>
<span class="fn">print</span>(<span class="var">bot</span>.<span class="fn">arbeiten</span>(<span class="num">3</span>)) <span class="cm"># Energie auf 0 -> schaltet ab</span>
<span class="fn">print</span>(<span class="var">bot</span>)
<span class="fn">print</span>(<span class="var">bot</span>.<span class="fn">aufladen</span>())</pre>
</div>
</section>
<!-- Aufgaben Card -->
<!-- 3. Aufgaben Card -->
<section class="card">
<h2>2. Deine Aufgaben in <code>aufgabe.py</code></h2>
<h2>3. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<ul class="task-list">
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_1">
<label for="t6_1" class="task-label">
<strong>TODO 1:</strong> Konstruktor <code>__init__(self, name, tierart="Drache")</code>: Startwerte <code>hunger=50</code>, <code>muedigkeit=20</code>, <code>glueck=80</code>, <code>alter_tage=0</code>, <code>ist_lebendig=True</code>.
<strong>TODO 1:</strong> <code>__init__(self, name, tierart="Drache")</code>: Startwerte <code>hunger=50</code>, <code>muedigkeit=20</code>, <code>glueck=80</code>, <code>alter_tage=0</code>, <code>ist_lebendig=True</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_2">
<label for="t6_2" class="task-label">
<strong>TODO 2:</strong> Methode <code>fuettern(self, menge=20)</code>: Senkt Hunger, erhöht Glück &amp; Müdigkeit um 5.
<strong>TODO 2:</strong> <code>fuettern(self, menge=20)</code>: Senkt Hunger, erhöht Glück &amp; Müdigkeit um 5.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_3">
<label for="t6_3" class="task-label">
<strong>TODO 3:</strong> Methode <code>spielen(self, spass=25)</code>: Steigert Glück, erhöht Hunger (15) &amp; Müdigkeit (20). Wenn <code>muedigkeit > 80</code> -> ablehnen!
<strong>TODO 3:</strong> <code>spielen(self, spass=25)</code>: Steigert Glück, erhöht Hunger (15) &amp; Müdigkeit (20). Wenn <code>muedigkeit > 80</code> -> ablehnen!
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_4">
<label for="t6_4" class="task-label">
<strong>TODO 4:</strong> Methode <code>schlafen(self)</code>: Müdigkeit auf 0, Hunger +15, <code>alter_tage += 1</code>.
<strong>TODO 4:</strong> <code>schlafen(self)</code>: Müdigkeit auf 0, Hunger +15, <code>alter_tage += 1</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_5">
<label for="t6_5" class="task-label">
<strong>TODO 5:</strong> Methode <code>zeit_vergeht(self)</code>: Hunger +10, Müdigkeit +10, Glück -10. Prüfen, ob Hunger &gt;= 100 oder Glück &lt;= 0.
<strong>TODO 5:</strong> <code>zeit_vergeht(self)</code>: Hunger +10, Müdigkeit +10, Glück -10. Prüfen, ob Hunger &gt;= 100 oder Glück &lt;= 0.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t6_6">
<label for="t6_6" class="task-label">
<strong>TODO 6:</strong> Dunder-Methode <code>__str__(self)</code>: Statusanzeige mit Name, Tierart, Alter und Werten.
<strong>TODO 6:</strong> <code>__str__(self)</code>: Übersicht mit Name, Tierart, Alter und Werten.
</label>
</li>
</ul>
@ -93,9 +139,9 @@
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>Tipp zur Werte-Begrenzung (Clamping)</summary>
<summary>🔍 Tipp zur Werte-Begrenzung (Clamping)</summary>
<div class="details-content">
<p>Damit Werte nicht negativ werden oder 100 überschreiten, kannst du die Hilfsfunktion <code>max(0, min(100, wert))</code> nutzen:</p>
<p>Damit Werte nicht unter 0 fallen oder über 100 steigen, nutze <code>max(0, min(100, wert))</code>:</p>
<div class="code-container">
<pre><span class="var">self</span>.<span class="attr">hunger</span> = <span class="fn">max</span>(<span class="num">0</span>, <span class="fn">min</span>(<span class="num">100</span>, <span class="var">self</span>.<span class="attr">hunger</span> - <span class="var">menge</span>))</pre>
</div>
@ -103,11 +149,11 @@
</details>
</section>
<!-- Spiel starten Card -->
<!-- 4. Spiel starten Card -->
<section class="card">
<h2>3. Das interaktive Spiel starten! 🕹️</h2>
<h2>4. 🕹️ Das interaktive Spiel starten!</h2>
<p>Sobald deine Tests grün sind, kannst du das Spiel live spielen:</p>
<p>Sobald alle Unittests grün sind, kannst du das Spiel live spielen:</p>
<div class="code-container">
<div class="code-header">
@ -117,8 +163,8 @@
</div>
<div class="box box-success">
<div class="box-title">🎉 Geschafft!</div>
Du hast damit erfolgreich gelernt, wie man objektorientiert in Python programmiert!
<div class="box-title">🎉 Du hast es geschafft!</div>
Herzlichen Glückwunsch zum erfolgreichen Abschluss der Python OOP Übungsreihe!
</div>
<div class="footer-nav">