Füge Vorkapitel 00 zur Fehlersuche und Python-Debugging (Bug-Hunt Detektiv-Aufgabe) hinzu

This commit is contained in:
Alex Mueller 2026-08-29 13:09:09 +02:00
parent 35f57ac484
commit b0e53d3e09
9 changed files with 490 additions and 38 deletions

View file

@ -0,0 +1,53 @@
# Vorkapitel 00: Python Fehlersuche & Grundlagen 🔍🕵️‍♀️
Herzlich willkommen zum Warm-up!
Bevor wir mit Klassen und objektorientierter Programmierung starten, lernen wir das wichtigste Handwerkszeug jeder guten Entwicklerin: **Wie man Fehler im Code schnell findet und behebt.**
---
## 💡 Fehlermeldungen richtig lesen: Die Unten-nach-Oben-Regel
Wenn Python stoppt und einen roten Text anzeigt, nennt man das einen **Traceback**.
Lies immer ganz unten:
```text
Traceback (most recent call last):
File "aufgabe.py", line 15, in <module>
summe = punkte + bonus
TypeError: unsupported operand type(s) for +: 'int' and 'str'
```
1. **Ganz unten:** Was ist das Problem? (`TypeError: ... 'int' and 'str'`)
2. **Zeile darüber:** Wo ist es passiert? (`line 15`)
---
## 🚫 Die 4 häufigsten Python-Fehler
1. **`IndentationError`:**
In Python müssen Codeblöcke in Funktionen, Bedingungen und Schleifen **genau 4 Leerzeichen** eingerückt sein.
2. **`SyntaxError`:**
Doppelpunkte am Ende von `def`, `if`, `else`, `for` vergessen oder ungeschlossene Klammern `)`.
3. **`NameError`:**
Tippfehler beim Namen einer Variable oder Funktion (z.B. `spielr_name` statt `spieler_name`).
4. **`TypeError`:**
Falsche Datentypen gemischt (z.B. `"Ergebnis: " + 10` statt `f"Ergebnis: {10}"`).
---
## 🎯 Deine Detektiv-Aufgabe in `aufgabe.py`
In `aufgabe.py` hat sich ein fehlerhaftes Quiz-Programm eingeschlichen. Deine Aufgabe ist es, die 5 versteckten Fehler zu finden und zu reparieren.
### Vorgehen:
1. Führe die Datei im Terminal aus:
```bash
python3 aufgabe.py
```
2. Lies die Fehlermeldung von unten nach oben.
3. Behebe den ersten angezeigten Fehler.
4. Wiederhole die Schritte, bis das Skript ohne Fehler durchläuft!
5. Führe den Test zur Bestätigung aus:
```bash
python3 test_aufgabe.py
```

View file

@ -0,0 +1,76 @@
"""
Vorkapitel 00: Python-Detektivin – Finde die 5 versteckten Fehler!
==================================================================
In diesem Skript haben sich 5 typische Python-Fehler eingeschlichen.
Führe das Skript mit 'python3 aufgabe.py' aus, lies die Fehlermeldungen
und behebe die Fehler der Reihe nach von BUG 1 bis BUG 5.
"""
# ==============================================================================
# BUG 1 & BUG 2: SyntaxError & IndentationError
# In dieser Funktion fehlen ein Doppelpunkt ':' und die Einrückung stimmt nicht!
# ==============================================================================
def berechne_endstand(basis_punkte, bonus)
gesamt = basis_punkte + bonus
if bonus > 10:
gesamt += 5 # Hier ist ein Einrückungsfehler!
return gesamt
# ==============================================================================
# BUG 3: NameError
# Hier hat sich ein Tippfehler bei einem Variablennamen eingeschlichen!
# ==============================================================================
def punkte_multiplizieren(spieler_punkte, faktor):
# Finde den Tippfehler im Variablennamen:
ergebnis = spiler_punkte * faktor
return ergebnis
# ==============================================================================
# BUG 4: TypeError
# Hier wird versucht, eine Zahl und einen Text mit '+' zusammenzufügen.
# Tipp: Nutze stattdessen einen sauberen f-String: f"Spieler {name} hat {punkte} Punkte!"
# ==============================================================================
def formatierte_ausgabe(name, punkte):
text = "Spieler " + name + " hat " + punkte + " Punkte!"
return text
# ==============================================================================
# BUG 5: Logik-Fehler (Vergleichsoperator)
# Diese Funktion soll True zurückgeben, wenn ein Spieler 50 ODER MEHR Punkte hat.
# Aktuell gibt sie bei genau 50 Punkten leider False zurück!
# ==============================================================================
def ist_sieger(punkte):
if punkte > 50:
return True
else:
return False
# ==============================================================================
# Hauptprogramm zum Ausprobieren:
# (Führe dieses Skript aus mit: python3 aufgabe.py)
# ==============================================================================
if __name__ == "__main__":
print("🕵️‍♀️ --- CODE-DETEKTIVIN QUIZ TEST --- 🕵️‍♀️")
# Test 1
endstand = berechne_endstand(20, 15)
print(f"Endstand (sollte 40 sein): {endstand}")
# Test 2
multipliziert = punkte_multiplizieren(10, 3)
print(f"Multipliziert (sollte 30 sein): {multipliziert}")
# Test 3
ausgabe = formatierte_ausgabe("Mia", 50)
print(f"Formatierte Ausgabe: {ausgabe}")
# Test 4
sieger = ist_sieger(50)
print(f"Ist 50 Punkte ein Sieg? (sollte True sein): {sieger}")
print("\n🎉 Herzlichen Glückwunsch! Alle 5 Bugs wurden erfolgreich behoben!")

View file

@ -0,0 +1,209 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kapitel 00: Fehlersuche & Grundlagen</title>
<link rel="stylesheet" href="../assets/style.css">
</head>
<body>
<header>
<div class="header-container">
<nav class="nav-links">
<a href="../index.html">🏠 Zur Kursübersicht</a>
<span>&rsaquo;</span>
<span style="color: white; font-weight: 600;">Kapitel 00</span>
<span>&rsaquo;</span>
<a href="../01_einstieg_klassen/index.html">Kapitel 01 &rarr;</a>
</nav>
<div class="header-badge">Vorkapitel 00</div>
<h1>Python Fehlersuche &amp; Grundlagen 🔍🕵️‍♀️</h1>
<p>Lerne, wie du Fehlermeldungen richtig liest, Einrückungsfehler behebst und Bugs wie eine echte Detektivin aufspürst.</p>
</div>
</header>
<main class="container">
<!-- 1. Keine Panik vor Fehlermeldungen -->
<section class="card">
<h2>1. Die wichtigste Regel: Keine Panik bei Fehlern!</h2>
<p>
Jeder Programmierer auf der Welt – selbst bei Google oder Apple – schreibt täglich dutzende Fehler.
</p>
<div class="box box-analogie">
<div class="box-title">💡 Der Computer ist dein Assistent, kein Richter:</div>
Wenn Python eine rote Fehlermeldung (einen sogenannten <strong>Traceback</strong>) anzeigt, ist das nichts Schlimmes. Der Computer sagt dir damit nur: <em>"Hey, hier verstehe ich in Zeile X etwas noch nicht ganz – kannst du mir kurz helfen?"</em>
</div>
<h3>Wie liest man einen Traceback? (Die Unten-nach-Oben-Regel)</h3>
<p>
Ein Traceback kann lang und einschüchternd wirken. Doch das Geheimnis ist: <strong>Lies immer ganz unten!</strong>
</p>
<div class="code-container">
<div class="code-header">
<span>Beispiel einer Fehlermeldung</span>
</div>
<pre>Traceback (most recent call last):
File "aufgabe.py", line 12, in berechne_rabatt
ergebnis = preis * rabatt_prozent
<span class="kw" style="color: #ef4444;">TypeError</span>: can't multiply sequence by non-int of type 'float'
<span class="cm">▲ ▲</span>
<span class="cm">1. ART DES FEHLERS 2. DIE ERKLÄRUNG</span></pre>
</div>
<p>
Ganz unten steht:
<br>1. <strong>Um welchen Fehler handelt es sich?</strong> (z.B. <code>TypeError</code>)
<br>2. <strong>Was genau ist schiefgelaufen?</strong> (z.B. Text mit Kommazahl multipliziert)
<br>3. Direkt in der Zeile darüber steht die <strong>Dateiname und Zeilennummer</strong> (z.B. <code>line 12</code>)!
</p>
</section>
<!-- 2. Die 4 häufigsten Anfängerfehler -->
<section class="card">
<h2>2. Die 4 häufigsten Python-Fehler im Überblick</h2>
<!-- Fehler 1: Indentation -->
<div class="box box-warning">
<div class="box-title">1. IndentationError (Einrückungsfehler)</div>
<p>In Python haben Einrückungen eine feste Bedeutung. Alles, was in einer Funktion, Schleife oder Bedingung steht, muss <strong>genau 4 Leerzeichen</strong> eingerückt sein.</p>
</div>
<div class="code-container">
<div class="code-header"><span>Vergleich: Einrückung</span></div>
<pre><span class="cm"># ❌ Falsch:</span>
<span class="kw">def</span> <span class="fn">begruessung</span>(<span class="var">name</span>):
<span class="fn">print</span>(<span class="str">"Hallo"</span>, <span class="var">name</span>) <span class="cm"># 💥 IndentationError: expected an indented block</span>
<span class="cm"># ✅ Richtig:</span>
<span class="kw">def</span> <span class="fn">begruessung</span>(<span class="var">name</span>):
<span class="fn">print</span>(<span class="str">"Hallo"</span>, <span class="var">name</span>) <span class="cm"># 4 Leerzeichen eingerückt!</span></pre>
</div>
<!-- Fehler 2: SyntaxError -->
<div class="box box-warning">
<div class="box-title">2. SyntaxError (Tippfehler &amp; fehlende Doppelpunkte)</div>
<p>Häufig vergessen: Der Doppelpunkt <code>:</code> am Ende von <code>def</code>, <code>if</code>, <code>else</code>, <code>for</code> oder <code>while</code>, oder eine ungeschlossene Klammer.</p>
</div>
<div class="code-container">
<div class="code-header"><span>Vergleich: Syntax</span></div>
<pre><span class="cm"># ❌ Falsch: Doppelpunkt vergessen</span>
<span class="kw">if</span> <span class="var">alter</span> >= <span class="num">18</span>
<span class="fn">print</span>(<span class="str">"Volljährig"</span>) <span class="cm"># 💥 SyntaxError: expected ':'</span>
<span class="cm"># ✅ Richtig:</span>
<span class="kw">if</span> <span class="var">alter</span> >= <span class="num">18</span>:
<span class="fn">print</span>(<span class="str">"Volljährig"</span>)</pre>
</div>
<!-- Fehler 3: NameError -->
<div class="box box-warning">
<div class="box-title">3. NameError (Unbekannter Name / Tippfehler)</div>
<p>Tritt auf, wenn eine Variable oder Funktion aufgerufen wird, die nicht existiert (oder falsch geschrieben wurde).</p>
</div>
<div class="code-container">
<div class="code-header"><span>Vergleich: NameError</span></div>
<pre><span class="var">spieler_name</span> = <span class="str">"Alex"</span>
<span class="fn">print</span>(<span class="var">spielr_name</span>) <span class="cm"># 💥 NameError: name 'spielr_name' is not defined (Tippfehler!)</span></pre>
</div>
<!-- Fehler 4: TypeError -->
<div class="box box-warning">
<div class="box-title">4. TypeError (Falscher Datentyp)</div>
<p>Tritt auf, wenn man Operationen mit unpassenden Typen versucht (z.B. Zahl an Text anhängen mit <code>+</code> statt f-String).</p>
</div>
<div class="code-container">
<div class="code-header"><span>Vergleich: TypeError</span></div>
<pre><span class="var">punkte</span> = <span class="num">100</span>
<span class="cm"># ❌ Falsch:</span>
<span class="fn">print</span>(<span class="str">"Du hast "</span> + <span class="var">punkte</span> + <span class="str">" Punkte!"</span>) <span class="cm"># 💥 TypeError: can only concatenate str to str</span>
<span class="cm"># ✅ Richtig mit f-String:</span>
<span class="fn">print</span>(<span class="str">f"Du hast {punkte} Punkte!"</span>)</pre>
</div>
</section>
<!-- 3. Detektiv-Aufgabe -->
<section class="card">
<h2>3. 🕵️‍♀️ Deine Detektiv-Aufgabe in <code>aufgabe.py</code></h2>
<p>
In der Datei <code>00_fehlersuche_und_grundlagen/aufgabe.py</code> findest du ein kleines Programm für ein Quiz-Spiel, in dem sich <strong>5 typische Fehler</strong> versteckt haben!
</p>
<p>Deine Mission als Code-Detektivin:</p>
<ul class="task-list">
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="b1">
<label for="b1" class="task-label">
<strong>Bug 1 (SyntaxError):</strong> Finde den fehlenden Doppelpunkt in der Funktionsdefinition <code>berechne_endstand</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="b2">
<label for="b2" class="task-label">
<strong>Bug 2 (IndentationError):</strong> Korrigiere die falsche Einrückung in der <code>if</code>-Bedingung.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="b3">
<label for="b3" class="task-label">
<strong>Bug 3 (NameError):</strong> Korrigiere den Tippfehler beim Variablennamen <code>spieler_punkte</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="b4">
<label for="b4" class="task-label">
<strong>Bug 4 (TypeError):</strong> Korrigiere die Textzusammensetzung in <code>formatierte_ausgabe</code> (nutze einen sauberen f-String).
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="b5">
<label for="b5" class="task-label">
<strong>Bug 5 (Logik-Fehler):</strong> Die Funktion <code>ist_sieger</code> soll ab <strong>50 Punkten oder mehr</strong> <code>True</code> zurückgeben (prüfe <code>&gt;=</code> statt <code>&gt;</code>).
</label>
</li>
</ul>
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>🔍 Tipp zur Ausführung im Terminal</summary>
<div class="details-content">
<p>Führe das Skript einfach direkt im Terminal aus:</p>
<div class="code-container">
<pre><code>python3 aufgabe.py</code></pre>
</div>
<p>Python zeigt dir sofort den ersten Fehler an. Repariere ihn, führe das Skript erneut aus und arbeite dich so Schritt für Schritt durch!</p>
</div>
</details>
</section>
<!-- 4. Testen & Navigation -->
<section class="card">
<h2>4. 🧪 Detektiv-Prüfung abschließen</h2>
<p>Sobald du alle Fehler behoben hast, teste deine Lösung mit:</p>
<div class="code-container">
<div class="code-header">
<span>Terminal</span>
</div>
<pre><code>python3 test_aufgabe.py</code></pre>
</div>
<div class="footer-nav">
<a href="../index.html" class="btn btn-secondary">&larr; Zurück zur Übersicht</a>
<a href="../01_einstieg_klassen/index.html" class="btn">Weiter zu Kapitel 01: Klassen &rarr;</a>
</div>
</section>
</main>
</body>
</html>

View file

@ -0,0 +1,40 @@
"""
Vorkapitel 00: Python-Detektivin – Musterlösung
==============================================
Hier ist die vollständig fehlerfreie Version des Skripts.
"""
# BUG 1 & 2 behoben: Doppelpunkt hinzugefügt und 'gesamt += 5' sauber eingerückt:
def berechne_endstand(basis_punkte, bonus):
gesamt = basis_punkte + bonus
if bonus > 10:
gesamt += 5
return gesamt
# BUG 3 behoben: Tippfehler 'spiler_punkte' -> 'spieler_punkte' korrigiert:
def punkte_multiplizieren(spieler_punkte, faktor):
ergebnis = spieler_punkte * faktor
return ergebnis
# BUG 4 behoben: f-String verwendet, um Zahl und Text sauber zu verbinden:
def formatierte_ausgabe(name, punkte):
text = f"Spieler {name} hat {punkte} Punkte!"
return text
# BUG 5 behoben: >= statt > verwendet:
def ist_sieger(punkte):
if punkte >= 50:
return True
else:
return False
if __name__ == "__main__":
print("🕵️‍♀️ --- CODE-DETEKTIVIN QUIZ TEST (Musterlösung) --- 🕵️‍♀️")
print("Endstand (40):", berechne_endstand(20, 15))
print("Multipliziert (30):", punkte_multiplizieren(10, 3))
print("Ausgabe:", formatierte_ausgabe("Mia", 50))
print("Sieg bei 50:", ist_sieger(50))

View file

@ -0,0 +1,63 @@
import unittest
import sys
import importlib
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
class TestKapitel00(unittest.TestCase):
@classmethod
def setUpClass(cls):
# Wenn ein Test-Runner vorher 'aufgabe' durch ein anderes Modul ersetzt hat (z.B. musterloesung):
if hasattr(cls, "modul_name"):
cls.mod = importlib.import_module(cls.modul_name)
else:
try:
cls.mod = importlib.import_module("aufgabe")
except SyntaxError as e:
cls.mod = None
cls.import_error = f"SyntaxError in 'aufgabe.py': {e}. Überprüfe Doppelpunkte und Einrückungen!"
except Exception as e:
cls.mod = None
cls.import_error = f"Fehler beim Import von 'aufgabe.py': {e}"
def _get_modul(self):
if getattr(self, "mod", None) is None:
err = getattr(self, "import_error", "aufgabe.py konnte nicht importiert werden")
self.fail(f"❌ {err}")
return self.mod
def test_01_berechne_endstand(self):
"""Prüft berechne_endstand (Syntax & Einrückung behoben)."""
mod = self._get_modul()
self.assertTrue(hasattr(mod, "berechne_endstand"), "Funktion 'berechne_endstand' fehlt!")
self.assertEqual(mod.berechne_endstand(20, 15), 40, "berechne_endstand(20, 15) sollte 40 sein (inkl. Bonus)!")
self.assertEqual(mod.berechne_endstand(20, 5), 25, "berechne_endstand(20, 5) sollte 25 sein!")
def test_02_punkte_multiplizieren(self):
"""Prüft punkte_multiplizieren (Tippfehler NameError behoben)."""
mod = self._get_modul()
self.assertTrue(hasattr(mod, "punkte_multiplizieren"), "Funktion 'punkte_multiplizieren' fehlt!")
self.assertEqual(mod.punkte_multiplizieren(10, 3), 30)
self.assertEqual(mod.punkte_multiplizieren(7, 2), 14)
def test_03_formatierte_ausgabe(self):
"""Prüft formatierte_ausgabe (TypeError behoben)."""
mod = self._get_modul()
self.assertTrue(hasattr(mod, "formatierte_ausgabe"), "Funktion 'formatierte_ausgabe' fehlt!")
ergebnis = mod.formatierte_ausgabe("Mia", 50)
self.assertEqual(ergebnis, "Spieler Mia hat 50 Punkte!")
def test_04_ist_sieger_grenzwert(self):
"""Prüft Logik von ist_sieger (>= 50 Punkte)."""
mod = self._get_modul()
self.assertTrue(hasattr(mod, "ist_sieger"), "Funktion 'ist_sieger' fehlt!")
self.assertTrue(mod.ist_sieger(50), "Fehler: Genau 50 Punkte müssen True (Sieg) ergeben (>= 50)!")
self.assertTrue(mod.ist_sieger(100), "100 Punkte müssen True ergeben!")
self.assertFalse(mod.ist_sieger(49), "49 Punkte dürfen noch kein Sieg sein (False)!")
if __name__ == "__main__":
unittest.main(verbosity=2)

View file

@ -13,6 +13,8 @@
<nav class="nav-links"> <nav class="nav-links">
<a href="../index.html">🏠 Zur Kursübersicht</a> <a href="../index.html">🏠 Zur Kursübersicht</a>
<span>&rsaquo;</span> <span>&rsaquo;</span>
<a href="../00_fehlersuche_und_grundlagen/index.html">Kapitel 00</a>
<span>&rsaquo;</span>
<span style="color: white; font-weight: 600;">Kapitel 01</span> <span style="color: white; font-weight: 600;">Kapitel 01</span>
</nav> </nav>
<div class="header-badge">Kapitel 01</div> <div class="header-badge">Kapitel 01</div>
@ -278,7 +280,7 @@
</div> </div>
<div class="footer-nav"> <div class="footer-nav">
<a href="../index.html" class="btn btn-secondary">&larr; Zurück zur Übersicht</a> <a href="../00_fehlersuche_und_grundlagen/index.html" class="btn btn-secondary">&larr; Zurück zu Kapitel 00</a>
<a href="../02_init_und_self/index.html" class="btn">Weiter zu Kapitel 02 &rarr;</a> <a href="../02_init_und_self/index.html" class="btn">Weiter zu Kapitel 02 &rarr;</a>
</div> </div>
</section> </section>

View file

@ -12,6 +12,7 @@ Die Übungen sind so aufgebaut, dass jedes Kapitel auf dem vorherigen aufbaut:
| Kapitel | Thema | Was du lernst | | Kapitel | Thema | Was du lernst |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **[00. Fehlersuche & Grundlagen](./00_fehlersuche_und_grundlagen/)** | Warm-up & Debugging | Tracebacks lesen, Einrückungen (`IndentationError`), Typfehler & Detektiv-Aufgabe |
| **[01. Einstieg in Klassen](./01_einstieg_klassen/)** | Warum Klassen? | Bauplan vs. Objekt, Instanziierung & Attribute | | **[01. Einstieg in Klassen](./01_einstieg_klassen/)** | Warum Klassen? | Bauplan vs. Objekt, Instanziierung & Attribute |
| **[02. Konstruktor & self](./02_init_und_self/)** | `__init__` & `self` | Objekte sauber mit Startwerten initialisieren | | **[02. Konstruktor & self](./02_init_und_self/)** | `__init__` & `self` | Objekte sauber mit Startwerten initialisieren |
| **[03. Methoden & Verhalten](./03_methoden_und_verhalten/)** | Methoden & Interaktion | Objekte können handeln & miteinander interagieren | | **[03. Methoden & Verhalten](./03_methoden_und_verhalten/)** | Methoden & Interaktion | Objekte können handeln & miteinander interagieren |
@ -24,30 +25,28 @@ Die Übungen sind so aufgebaut, dass jedes Kapitel auf dem vorherigen aufbaut:
## 📁 Aufbau eines Kapitels ## 📁 Aufbau eines Kapitels
In jedem Kapitelordner findest du: In jedem Kapitelordner findest du:
1. **`README.md`**: Eine verständliche Erklärung mit Analogien aus dem Alltag und Codebeispielen. 1. **`index.html`**: Eine interaktive, schön gestaltete Webseite mit ausführlichen Erklärungen, Vollbeispielen und aufklappbaren Lösungshinweisen.
2. **`aufgabe.py`**: Dein Arbeitsblatt! Hier steht der Starter-Code mit klaren `TODO`-Kommentaren. 2. **`README.md`**: Die Erklärung im Markdown-Format.
3. **`test_aufgabe.py`**: Automatische Tests, mit denen du deine Lösung jederzeit überprüfen kannst. 3. **`aufgabe.py`**: Dein Arbeitsblatt! Hier steht der Starter-Code mit klaren `TODO`-Kommentaren.
4. **`musterloesung.py`**: Eine ausführlich kommentierte Beispiellösung (falls du mal nicht weiterkommst oder vergleichen möchtest). 4. **`test_aufgabe.py`**: Automatische Tests, mit denen du deine Lösung jederzeit überprüfen kannst.
5. **`musterloesung.py`**: Eine ausführlich kommentierte Beispiellösung.
--- ---
## 🚀 Wie du vorgehst ## 🚀 Wie du vorgehst
1. Öffne den Ordner des aktuellen Kapitels (z.B. `01_einstieg_klassen`). 1. Öffne den Ordner des aktuellen Kapitels (z.B. `00_fehlersuche_und_grundlagen`).
2. Lies dir die Erklärung in der jeweiligen `README.md` durch. 2. Öffne die `index.html` im Browser oder lies die `README.md`.
3. Öffne `aufgabe.py` und bearbeite die nummerierten `TODO`s. 3. Öffne `aufgabe.py` und bearbeite die nummerierten `TODO`s / Bugs.
4. Führe die Tests aus, um deine Lösung zu prüfen: 4. Führe die Tests aus, um deine Lösung zu prüfen:
```bash ```bash
# Aus dem Hauptverzeichnis:
python3 -m unittest 01_einstieg_klassen/test_aufgabe.py
# Oder direkt im Ordner:
cd 01_einstieg_klassen
python3 test_aufgabe.py python3 test_aufgabe.py
``` ```
5. Wenn alle Tests mit einem grünen `OK` durchlaufen: **Herzlichen Glückwunsch!** Du bist bereit für das nächste Kapitel! 🏆 5. Wenn alle Tests mit einem grünen `OK` durchlaufen: **Herzlichen Glückwunsch!** Du bist bereit für das nächste Kapitel! 🏆
--- ---
## 💡 Tipp zum Lernen ## 💡 Gesamten Fortschritt prüfen
Versuche zuerst selbst eine Lösung zu finden. Wenn ein Fehler auftritt, lies die Fehlermeldung der Tests aufmerksam durch – sie gibt dir oft schon den entscheidenden Hinweis! Wenn du gar nicht weiterkommst, wirf einen Blick in `musterloesung.py` und versuche zu verstehen, wie das Problem gelöst wurde. ```bash
python3 test_all.py
```

View file

@ -26,26 +26,36 @@
Jetzt machen wir den nächsten großen Schritt in der Softwareentwicklung: <strong>Klassen & Objekte</strong>! Jetzt machen wir den nächsten großen Schritt in der Softwareentwicklung: <strong>Klassen & Objekte</strong>!
</p> </p>
<p> <p>
Mit Klassen kannst du zusammengehörige Daten und Aktionen an einem Ort bündeln. Fast jede moderne App (ob Instagram, Spotify oder Computerspiele) basiert auf objektorientierter Programmierung. Damit du beim Programmieren nie an kleinen Syntaxfehlern verzweifelst, starten wir mit einem kurzen <strong>Warm-up zur Fehlersuche (Kapitel 00)</strong>, bevor es mit den Klassen losgeht.
</p> </p>
<div class="box box-analogie"> <div class="box box-analogie">
<div class="box-title">🏗️ Die Grundidee in einem Satz:</div> <div class="box-title">🏗️ Die Grundidee von OOP in einem Satz:</div>
Eine <strong>Klasse</strong> ist wie ein Bauplan (oder eine Plätzchen-Ausstechform). Ein <strong>Objekt</strong> ist das fertige Haus (oder das gebackene Plätzchen), das nach diesem Bauplan entstanden ist! Eine <strong>Klasse</strong> ist wie ein Bauplan (oder eine Plätzchen-Ausstechform). Ein <strong>Objekt</strong> ist das fertige Haus (oder das gebackene Plätzchen), das nach diesem Bauplan entstanden ist!
</div> </div>
</section> </section>
<!-- Roadmap Grid --> <!-- Roadmap Grid -->
<section> <section>
<h2 style="margin: 30px 0 15px 0; color: var(--text-main); font-size: 1.5rem;">🗺️ Dein Lernpfad (Kapitel 01 bis 06)</h2> <h2 style="margin: 30px 0 15px 0; color: var(--text-main); font-size: 1.5rem;">🗺️ Dein Lernpfad (Kapitel 00 bis 06)</h2>
<div class="roadmap-grid"> <div class="roadmap-grid">
<!-- Kapitel 0 -->
<a href="00_fehlersuche_und_grundlagen/index.html" class="roadmap-card" style="border-left: 4px solid var(--purple);">
<div>
<span class="roadmap-number" style="background: var(--purple-light); color: var(--purple);">Vorkapitel 00</span>
<div class="roadmap-title">🔍 Fehlersuche &amp; Bugs</div>
<div class="roadmap-desc">Tracebacks richtig lesen, Einrückungsfehler (IndentationError), Typfehler und eine interaktive Detektiv-Aufgabe.</div>
</div>
<div class="roadmap-footer">Vorkapitel öffnen &rarr;</div>
</a>
<!-- Kapitel 1 --> <!-- Kapitel 1 -->
<a href="01_einstieg_klassen/index.html" class="roadmap-card"> <a href="01_einstieg_klassen/index.html" class="roadmap-card">
<div> <div>
<span class="roadmap-number">Kapitel 01</span> <span class="roadmap-number">Kapitel 01</span>
<div class="roadmap-title">🐶 Die erste Klasse</div> <div class="roadmap-title">🐶 Die erste Klasse</div>
<div class="roadmap-desc">Was ist eine Klasse? Bauplan vs. Objekt, Instanziierung und erste Attribute am Haustier-Beispiel.</div> <div class="roadmap-desc">Was ist eine Klasse? Bauplan vs. Objekt, Instanziierung und erste Attribute am Haustier- &amp; Fahrrad-Beispiel.</div>
</div> </div>
<div class="roadmap-footer">Kapitel öffnen &rarr;</div> <div class="roadmap-footer">Kapitel öffnen &rarr;</div>
</a> </a>
@ -55,7 +65,7 @@
<div> <div>
<span class="roadmap-number">Kapitel 02</span> <span class="roadmap-number">Kapitel 02</span>
<div class="roadmap-title">💳 Konstruktor & self</div> <div class="roadmap-title">💳 Konstruktor & self</div>
<div class="roadmap-desc">Wie <code>__init__</code> Objekte startklar macht und was das Wörtchen <code>self</code> wirklich bedeutet (Bankkonto-App).</div> <div class="roadmap-desc">Wie <code>__init__</code> Objekte startklar macht und was <code>self</code> bedeutet (Smartphone- &amp; Bankkonto-App).</div>
</div> </div>
<div class="roadmap-footer">Kapitel öffnen &rarr;</div> <div class="roadmap-footer">Kapitel öffnen &rarr;</div>
</a> </a>
@ -65,7 +75,7 @@
<div> <div>
<span class="roadmap-number">Kapitel 03</span> <span class="roadmap-number">Kapitel 03</span>
<div class="roadmap-title">⚔️ Methoden & Verhalten</div> <div class="roadmap-title">⚔️ Methoden & Verhalten</div>
<div class="roadmap-desc">Objekte führen Aktionen aus! Interaktion zwischen Helden und Monstern in einem RPG-Kampfsimulator.</div> <div class="roadmap-desc">Objekte führen Aktionen aus! Interaktion zwischen Objekten in Rennautos und RPG-Heldenduellen.</div>
</div> </div>
<div class="roadmap-footer">Kapitel öffnen &rarr;</div> <div class="roadmap-footer">Kapitel öffnen &rarr;</div>
</a> </a>
@ -75,7 +85,7 @@
<div> <div>
<span class="roadmap-number">Kapitel 04</span> <span class="roadmap-number">Kapitel 04</span>
<div class="roadmap-title">🧾 Schöne Textausgabe</div> <div class="roadmap-title">🧾 Schöne Textausgabe</div>
<div class="roadmap-desc">Wie man <code>print(objekt)</code> mit <code>__str__</code> lesbar macht und Objekte im Warenkorb sammelt.</div> <div class="roadmap-desc">Wie man <code>print(objekt)</code> mit <code>__str__</code> lesbar macht und Objekte im Warenkorb &amp; bei Pizza-Bestellungen sammelt.</div>
</div> </div>
<div class="roadmap-footer">Kapitel öffnen &rarr;</div> <div class="roadmap-footer">Kapitel öffnen &rarr;</div>
</a> </a>
@ -85,7 +95,7 @@
<div> <div>
<span class="roadmap-number">Kapitel 05</span> <span class="roadmap-number">Kapitel 05</span>
<div class="roadmap-title">🎵 Komposition & Playlists</div> <div class="roadmap-title">🎵 Komposition & Playlists</div>
<div class="roadmap-desc">Objekte verwalten andere Objekte: Song-Suche, Längenberechnung und Filter in Spotify-Playlists.</div> <div class="roadmap-desc">Objekte verwalten andere Objekte: Song-Suche, Längenberechnung und Filter in Spotify-Playlists &amp; Schulklassen.</div>
</div> </div>
<div class="roadmap-footer">Kapitel öffnen &rarr;</div> <div class="roadmap-footer">Kapitel öffnen &rarr;</div>
</a> </a>
@ -107,9 +117,9 @@
<section class="card"> <section class="card">
<h2>🚀 Wie du vorgehst (Schritt-für-Schritt)</h2> <h2>🚀 Wie du vorgehst (Schritt-für-Schritt)</h2>
<ol style="margin-left: 20px; margin-bottom: 15px;"> <ol style="margin-left: 20px; margin-bottom: 15px;">
<li style="margin-bottom: 8px;">Wähle das nächste offene Kapitel aus der Liste oben.</li> <li style="margin-bottom: 8px;">Wähle das nächste offene Kapitel aus der Liste oben (am besten startest du mit Kapitel 00).</li>
<li style="margin-bottom: 8px;">Lies die Erklärungen und schau dir die Codebeispiele und „Stolperfallen“ an.</li> <li style="margin-bottom: 8px;">Lies die Erklärungen und schau dir die vollständigen Codebeispiele an.</li>
<li style="margin-bottom: 8px;">Öffne die <code>aufgabe.py</code> im entsprechenden Kapitelordner und löse die <code>TODO</code>s.</li> <li style="margin-bottom: 8px;">Öffne die <code>aufgabe.py</code> im entsprechenden Kapitelordner und löse die Aufgaben.</li>
<li style="margin-bottom: 8px;"> <li style="margin-bottom: 8px;">
Führe im Terminal den automatischen Test aus: Führe im Terminal den automatischen Test aus:
<div class="code-container" style="margin: 10px 0;"> <div class="code-container" style="margin: 10px 0;">

View file

@ -11,6 +11,7 @@ import unittest
from pathlib import Path from pathlib import Path
KAPITEL = [ KAPITEL = [
("Kapitel 00: Python-Fehlersuche (Warm-up)", "00_fehlersuche_und_grundlagen"),
("Kapitel 01: Einstieg in Klassen", "01_einstieg_klassen"), ("Kapitel 01: Einstieg in Klassen", "01_einstieg_klassen"),
("Kapitel 02: Konstruktor & self", "02_init_und_self"), ("Kapitel 02: Konstruktor & self", "02_init_und_self"),
("Kapitel 03: Methoden & Verhalten", "03_methoden_und_verhalten"), ("Kapitel 03: Methoden & Verhalten", "03_methoden_und_verhalten"),
@ -21,9 +22,9 @@ KAPITEL = [
def main(): def main():
root = Path(__file__).parent.resolve() root = Path(__file__).parent.resolve()
print("=" * 60) print("=" * 65)
print("🎓 PYTHON OOP ÜBUNGSREIHE – GESAMTFORTSCHRITT") print("🎓 PYTHON OOP ÜBUNGSREIHE – GESAMTFORTSCHRITT")
print("=" * 60) print("=" * 65)
gesamt_bestanden = 0 gesamt_bestanden = 0
@ -42,31 +43,30 @@ def main():
runner = unittest.TextTestRunner(stream=open("/dev/null", "w"), verbosity=0) runner = unittest.TextTestRunner(stream=open("/dev/null", "w"), verbosity=0)
result = runner.run(suite) result = runner.run(suite)
# Modul aus sys.path und sys.modules entfernen für saubere Isolation # Module für saubere Isolation entfernen
if str(kapitel_pfad) in sys.path: if str(kapitel_pfad) in sys.path:
sys.path.remove(str(kapitel_pfad)) sys.path.remove(str(kapitel_pfad))
if "aufgabe" in sys.modules: for m in list(sys.modules.keys()):
del sys.modules["aufgabe"] if m in ("aufgabe", "test_aufgabe", "musterloesung"):
if "test_aufgabe" in sys.modules: del sys.modules[m]
del sys.modules["test_aufgabe"]
anzahl_tests = result.testsRun anzahl_tests = result.testsRun
erfolgreich = result.wasSuccessful() and anzahl_tests > 0 erfolgreich = result.wasSuccessful() and anzahl_tests > 0
if erfolgreich: if erfolgreich:
print(f" ✅ {titel:42s} ({anzahl_tests}/{anzahl_tests} Tests OK)") print(f" ✅ {titel:45s} ({anzahl_tests}/{anzahl_tests} Tests OK)")
gesamt_bestanden += 1 gesamt_bestanden += 1
else: else:
fehlgeschlagen = len(result.failures) + len(result.errors) fehlgeschlagen = len(result.failures) + len(result.errors)
print(f" ⏳ {titel:42s} (Noch offen / {fehlgeschlagen} Fehler)") print(f" ⏳ {titel:45s} (Noch offen / {fehlgeschlagen} Fehler)")
print("=" * 60) print("=" * 65)
print(f"Ergebnis: {gesamt_bestanden} von {len(KAPITEL)} Kapiteln vollständig gelöst!") print(f"Ergebnis: {gesamt_bestanden} von {len(KAPITEL)} Kapiteln vollständig gelöst!")
if gesamt_bestanden == len(KAPITEL): if gesamt_bestanden == len(KAPITEL):
print("🏆 PERFEKT! Du hast alle OOP-Aufgaben mit Bravour gemeistert! 🎉") print("🏆 PERFEKT! Du hast alle Aufgaben mit Bravour gemeistert! 🎉")
else: else:
print("💡 Öffne das nächste offene Kapitel und starte mit aufgabe.py!") print("💡 Öffne das nächste offene Kapitel und starte mit aufgabe.py!")
print("=" * 60) print("=" * 65)
if __name__ == "__main__": if __name__ == "__main__":