Aufgaben-Python/lehrpfad_2_oop_einstieg/04_str_und_darstellung/index.html

404 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<link rel="icon" type="image/svg+xml" href="../../assets/favicon.svg">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kapitel 04: __str__ und Darstellung</title>
<link rel="stylesheet" href="../../assets/style.css">
</head>
<body>
<div class="app-layout">
<aside class="app-sidebar">
<div class="sidebar-header">
<a href="../../index.html" class="sidebar-brand-link">
<div class="sidebar-logo">🐍</div>
<div>
<div class="sidebar-title">Python Portal</div>
<div class="sidebar-subtitle">Lernplattform</div>
</div>
</a>
</div>
<div class="sidebar-quick-nav">
<a href="../../index.html" class="sidebar-link">🏠 Startseite</a>
<a href="../../index.html#tutorial" class="sidebar-link">📖 Tutorial &amp; Workflow</a>
<a href="../../index.html#zertifikate" class="sidebar-link">🏆 Zertifikate</a>
</div>
<div class="sidebar-nav">
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🌱 1. Grundlagen</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">G01–G10</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_1_grundlagen/01_erste_schritte_taschenrechner/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧮</span>
<span class="sidebar-link-text">G01. Taschenrechner</span>
</a>
<a href="../../lehrpfad_1_grundlagen/02_variablen_und_datentypen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">📦</span>
<span class="sidebar-link-text">G02. Variablen & Typen</span>
</a>
<a href="../../lehrpfad_1_grundlagen/03_ein_und_ausgabe/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💬</span>
<span class="sidebar-link-text">G03. Ein- & Ausgabe</span>
</a>
<a href="../../lehrpfad_1_grundlagen/04_verzweigungen_und_bedingungen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🚦</span>
<span class="sidebar-link-text">G04. Bedingungen (if)</span>
</a>
<a href="../../lehrpfad_1_grundlagen/05_schleifen_und_wiederholungen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎡</span>
<span class="sidebar-link-text">G05. Schleifen (for/while)</span>
</a>
<a href="../../lehrpfad_1_grundlagen/06_funktionen_und_module/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🪄</span>
<span class="sidebar-link-text">G06. Funktionen & Module</span>
</a>
<a href="../../lehrpfad_1_grundlagen/07_listen_und_sequenzen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">📋</span>
<span class="sidebar-link-text">G07. Listen & Sequenzen</span>
</a>
<a href="../../lehrpfad_1_grundlagen/08_textverarbeitung_und_strings/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🔤</span>
<span class="sidebar-link-text">G08. String-Methoden</span>
</a>
<a href="../../lehrpfad_1_grundlagen/09_dictionaries_und_sets/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🗃️</span>
<span class="sidebar-link-text">G09. Dicts & Sets</span>
</a>
<a href="../../lehrpfad_1_grundlagen/10_comprehensions_datum_algorithmen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🚀</span>
<span class="sidebar-link-text">G10. Comprehensions</span>
</a>
</div>
</div>
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🏗️ 2. OOP Einstieg</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">00–06</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_2_oop_einstieg/00_fehlersuche_und_grundlagen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🔍</span>
<span class="sidebar-link-text">00. Fehlersuche & Debug</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/01_einstieg_klassen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🏗️</span>
<span class="sidebar-link-text">01. Einstieg in Klassen</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/02_init_und_self/index.html" class="sidebar-link">
<span class="sidebar-link-icon">⚙️</span>
<span class="sidebar-link-text">02. Konstruktor & self</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/03_methoden_und_verhalten/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🏎️</span>
<span class="sidebar-link-text">03. Methoden & Verhalten</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04_str_und_darstellung/index.html" class="sidebar-link active">
<span class="sidebar-link-icon">🧾</span>
<span class="sidebar-link-text">04. __str__ Darstellung</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04b_umstieg_vscode/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💻</span>
<span class="sidebar-link-text">04b. VS Code Setup</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04c_git_und_versionskontrolle/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🌿</span>
<span class="sidebar-link-text">04c. Git-Versionskontrolle</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/05_objekte_kombinieren/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎵</span>
<span class="sidebar-link-text">05. Objekte kombinieren</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/06_abschlussprojekt_tamagotchi/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🥚</span>
<span class="sidebar-link-text">06. Projekt: Tamagotchi</span>
</a>
</div>
</div>
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🚀 3. Fortgeschritten</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">07–16</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_3_fortgeschrittenes_oop/07_referenzen_und_speicher/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧠</span>
<span class="sidebar-link-text">07. Referenzen & Speicher</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/08_operator_overloading_dunder/index.html" class="sidebar-link">
<span class="sidebar-link-icon">➕</span>
<span class="sidebar-link-text">08. Operator Overloading</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/09_eigene_unit_tests_schreiben/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧪</span>
<span class="sidebar-link-text">09. Unit Tests & TDD</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/10_vererbung_und_super/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧬</span>
<span class="sidebar-link-text">10. Vererbung & super()</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/11_polymorphie_und_interfaces/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎭</span>
<span class="sidebar-link-text">11. Polymorphie</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/12_exceptions_und_fehlerbehandlung/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🛡️</span>
<span class="sidebar-link-text">12. Exceptions & Fehler</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/13_persistenz_json_und_csv/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💾</span>
<span class="sidebar-link-text">13. Persistenz (JSON/CSV)</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/14_gui_mit_tkinter/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🖥️</span>
<span class="sidebar-link-text">14. Desktop-GUIs (Tkinter)</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/15_parameter_und_container/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎒</span>
<span class="sidebar-link-text">15. Container & *args</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/16_master_abschlussprojekt/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🏆</span>
<span class="sidebar-link-text">16. Master-Abschlussprojekt</span>
</a>
</div>
</div>
</div>
<div class="sidebar-footer">
<div style="display: flex; align-items: center; justify-content: space-between;">
<div style="font-size: 0.85rem; font-weight: 700; color: white;" id="sidebar-level-text">⭐ Level 1</div>
<div style="font-size: 0.82rem; font-weight: 700; color: #38bdf8;" id="sidebar-xp-text">0 XP</div>
</div>
</div>
</aside>
<div class="app-main">
<header>
<div class="header-container">
<nav class="nav-links">
<a href="../../index.html">🏠 Zur Kursübersicht</a>
<span>&rsaquo;</span>
<a href="../03_methoden_und_verhalten/index.html">Kapitel 03</a>
<span>&rsaquo;</span>
<span style="color: white; font-weight: 600;">Kapitel 04</span>
</nav>
<div class="header-badge">Kapitel 04</div>
<h1>Schöne Ausgaben mit <code>__str__</code> &amp; Objektlisten 🧾</h1>
<p>Lerne anhand eines Pizzeria-Beispiels, wie du <code>print(objekt)</code> formatierst und Objekte in Listen sammelst.</p>
</div>
</header>
<main class="container">
<!-- 📂 Schnellzugriff & Download aller Dateien dieser Einheit -->
<div style="background: #ffffff; border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 14px 20px; margin-bottom: 25px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; box-shadow: var(--shadow-sm);">
<div style="font-weight: 700; color: var(--text-main); display: flex; align-items: center; gap: 8px;">
<span>📂 Dateien dieser Einheit:</span>
</div>
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<a href="../../workspace.html?course=python&track=lehrpfad_2_oop_einstieg&chapter=04_str_und_darstellung" class="btn" style="background: #10b981; color: #fff; font-weight: 700;">💻 In Web-IDE öffnen &rarr;</a>
<a href="aufgabe.py" class="btn" style="padding: 6px 14px; font-size: 0.88rem; background: var(--primary);" download>📄 aufgabe.py (Startercode)</a>
<a href="test_aufgabe.py" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;" download>🧪 test_aufgabe.py (Tests)</a>
<a href="musterloesung.py" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;" download>💡 musterloesung.py (Lösung)</a>
<a href="README.md" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;">📖 README.md</a>
</div>
</div>
<!-- 1. Das Problem mit Standard print -->
<section class="card">
<h2>1. Warum sieht <code>print(objekt)</code> standardmäßig so kryptisch aus?</h2>
<p>
Wenn du versuchst, ein Objekt ohne die Dunder-Methode <code>__str__</code> auszudrucken:
</p>
<div class="code-container">
<pre><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: &lt;__main__.Buch object at 0x7fa2b0485d90&gt;</span></pre>
</div>
<p>
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 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">
<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: pizzeria.py)</span>
</div>
<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="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="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>
<!-- 3. Stolperfallen -->
<section class="card">
<h2>3. ⚠️ Wichtig bei <code>__str__</code></h2>
<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-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>
<!-- 4. Aufgaben Card -->
<section class="card">
<h2>4. 🎯 Deine Aufgaben in <code><a href="aufgabe.py" style="color: inherit; text-decoration: underline;">aufgabe.py</a></code></h2>
<ul class="task-list">
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t4_1">
<label for="t4_1" class="task-label">
<strong>TODO 1:</strong> <code>Artikel.__init__(self, name, preis, anzahl=1)</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t4_2">
<label for="t4_2" class="task-label">
<strong>TODO 2:</strong> <code>Artikel.gesamtpreis(self)</code> -> <code>self.preis * self.anzahl</code>.
</label>
</li>
<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> -> <code>"{anzahl}x {name} (je {preis:.2f} €) = {gesamtpreis:.2f} €"</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t4_4">
<label for="t4_4" class="task-label">
<strong>TODO 4-7:</strong> <code>Warenkorb</code> mit <code>artikel_hinzufuegen</code>, <code>gesamtsumme</code> und <code>bon_text</code>.
</label>
</li>
</ul>
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<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>):
<span class="var">zeilen</span> = [<span class="str">"--- KASSENZETTEL ---"</span>]
<span class="kw">for</span> <span class="var">artikel</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">artikel_liste</span>:
<span class="var">zeilen</span>.<span class="fn">append</span>(<span class="fn">str</span>(<span class="var">artikel</span>)) <span class="cm"># Nutzt automatisch __str__ des Artikels!</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.gesamtsumme():.2f} €"</span>)
<span class="kw">return</span> <span class="str">"\n"</span>.<span class="fn">join</span>(<span class="var">zeilen</span>)</pre>
</div>
</div>
</details>
</section>
<!-- 5. Testen & Navigation -->
<section class="card">
<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">
<span>Terminal</span>
</div>
<pre><code>python3 test_aufgabe.py</code></pre>
</div>
<div class="footer-nav">
<a href="../03_methoden_und_verhalten/index.html" class="btn btn-secondary">&larr; Zurück zu Kapitel 03</a>
<a href="../04b_umstieg_vscode/index.html" class="btn">Weiter zu Kapitel 04b: VS Code 🚀 &rarr;</a>
</div>
</section>
</main>
</div>
</div>
<button type="button" class="sidebar-mobile-toggle"><span>☰ Menü</span></button>
<div class="sidebar-overlay"></div>
<!-- Scripts -->
<script src="../../assets/gamification_data.js"></script>
<script src="../../assets/gamification.js"></script>
<script src="../../assets/interpreter.js"></script>
<script src="../../assets/certificate.js"></script>
<script src="../../assets/parsons.js"></script>
<script src="../../assets/runner.js"></script>
<script src="../../assets/ui_enhancements.js"></script>
<script src="../../assets/sidebar.js"></script>
</body>
</html>