Aufgaben-Python/07_referenzen_und_speicher/index.html

215 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kapitel 07: Referenzen, Speicher & Stammbäume</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>
<a href="../06_abschlussprojekt_tamagotchi/index.html">Kapitel 06</a>
<span>&rsaquo;</span>
<span style="color: white; font-weight: 600;">Kapitel 07</span>
</nav>
<div class="header-badge">Kapitel 07 &bull; Fortgeschrittenes OOP</div>
<h1>Referenzen, Speicher &amp; Stammbäume 🧠🌳</h1>
<p>Verstehe, wie Python Objekte im Arbeitsspeicher verwaltet, was Aliasing bedeutet und baue einen echten Familienstammbaum.</p>
</div>
</header>
<main class="container">
<!-- 1. Das Konzept: Variablen sind Zeiger -->
<section class="card">
<h2>1. Was ist eine Referenz? (Variablen sind Namensschilder)</h2>
<p>
Viele glauben, eine Variable sei eine Box, in der das Objekt direkt drinliegt. In Python ist das anders:
<strong>Eine Variable ist in Wirklichkeit ein Zeiger (eine Referenz)</strong> auf einen Bereich im Arbeitsspeicher (RAM).
</p>
<div class="box box-analogie">
<div class="box-title">🏷️ Die Namensschild-Analogie:</div>
Stelle dir ein Haus vor. Das Haus steht an einer festen Adresse.
Die Variable ist nur ein <strong>Adresszettel</strong>. Wenn du schreibst <code>b = a</code>, baust du kein zweites Haus, sondern schreibst die gleiche Adresse einfach auf einen zweiten Zettel!
</div>
<h3>Das Phänomen: Was passiert bei <code>b = a</code>?</h3>
<div class="code-container">
<div class="code-header">
<span>Beispiel: Listen-Referenzen (Aliasing)</span>
</div>
<pre><span class="var">liste_a</span> = [<span class="num">1</span>, <span class="num">2</span>, <span class="num">3</span>]
<span class="var">liste_b</span> = <span class="var">liste_a</span> <span class="cm"># liste_b zeigt auf GENAU DIESELBE Liste im Speicher!</span>
<span class="var">liste_b</span>.<span class="fn">append</span>(<span class="num">99</span>)
<span class="fn">print</span>(<span class="var">liste_a</span>) <span class="cm"># Ausgabe: [1, 2, 3, 99] &lt;-- liste_a hat sich mitverändert!</span></pre>
</div>
<div class="box box-warning">
<div class="box-title">⚠️ Vorsicht bei veränderlichen Objekten (Mutable vs. Immutable):</div>
<ul>
<li><strong>Mutable (veränderlich):</strong> Listen, Dictionaries, eigene Klassenobjekte. Wenn du sie an einer Stelle änderst, ändern sich alle Variablen, die darauf zeigen!</li>
<li><strong>Immutable (unveränderlich):</strong> Zahlen (<code>int</code>, <code>float</code>), Texte (<code>str</code>), Tupel (<code>tuple</code>). Beim Ändern wird automatisch ein neues Objekt im Speicher erzeugt.</li>
</ul>
</div>
</section>
<!-- 2. is vs == -->
<section class="card">
<h2>2. Der Unterschied zwischen <code>==</code> und <code>is</code></h2>
<p>In Python gibt es zwei Arten von Vergleichen:</p>
<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
<thead>
<tr style="background: var(--primary-light); text-align: left;">
<th style="padding: 10px; border: 1px solid var(--border-color);">Operator</th>
<th style="padding: 10px; border: 1px solid var(--border-color);">Bedeutung</th>
<th style="padding: 10px; border: 1px solid var(--border-color);">Frage im Hintergrund</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 10px; border: 1px solid var(--border-color);"><code>==</code></td>
<td style="padding: 10px; border: 1px solid var(--border-color);"><strong>Wertegleichheit</strong></td>
<td style="padding: 10px; border: 1px solid var(--border-color);">Haben beide Objekte denselben Inhalt?</td>
</tr>
<tr style="background: #fafafa;">
<td style="padding: 10px; border: 1px solid var(--border-color);"><code>is</code></td>
<td style="padding: 10px; border: 1px solid var(--border-color);"><strong>Identität</strong></td>
<td style="padding: 10px; border: 1px solid var(--border-color);">Sind beide Variablen exakt dasselbe Objekt an derselben Speicheradresse?</td>
</tr>
</tbody>
</table>
<div class="code-container">
<pre><span class="var">x</span> = [<span class="num">1</span>, <span class="num">2</span>, <span class="num">3</span>]
<span class="var">y</span> = [<span class="num">1</span>, <span class="num">2</span>, <span class="num">3</span>]
<span class="var">z</span> = <span class="var">x</span>
<span class="fn">print</span>(<span class="var">x</span> == <span class="var">y</span>) <span class="cm"># True (weil der Inhalt gleich ist)</span>
<span class="fn">print</span>(<span class="var">x</span> <span class="kw">is</span> <span class="var">y</span>) <span class="cm"># False (zwei getrennte Listen im Speicher)</span>
<span class="fn">print</span>(<span class="var">x</span> <span class="kw">is</span> <span class="var">z</span>) <span class="cm"># True (z zeigt direkt auf dieselbe Liste wie x)</span></pre>
</div>
</section>
<!-- 3. Das Praxisbeispiel: Familienstammbaum -->
<section class="card">
<h2>3. Praxisbeispiel: Der Familienstammbaum 🌳</h2>
<p>
Warum sind Referenzen so genial? Weil ein und dasselbe Objekt in vielen Beziehungen vorkommen kann.
Eine Person namens <strong>Susi</strong> ist gleichzeitig die <em>Mutter von Erika</em>, das <em>Kind von Fritz</em> und die <em>Schwester von Tom</em>.
</p>
<div class="code-container">
<div class="code-header">
<span>Stammbaum mit Klassen-Referenzen</span>
</div>
<pre><span class="kw">class</span> <span class="fn">Person</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>: <span class="fn">str</span>, <span class="var">geburtsjahr</span>: <span class="fn">int</span>):
<span class="var">self</span>.<span class="attr">name</span>: <span class="fn">str</span> = <span class="var">name</span>
<span class="var">self</span>.<span class="attr">geburtsjahr</span>: <span class="fn">int</span> = <span class="var">geburtsjahr</span>
<span class="var">self</span>.<span class="attr">mutter</span>: <span class="fn">Person</span> | <span class="kw">None</span> = <span class="kw">None</span> <span class="cm"># Referenz auf Mutter-Objekt</span>
<span class="var">self</span>.<span class="attr">vater</span>: <span class="fn">Person</span> | <span class="kw">None</span> = <span class="kw">None</span> <span class="cm"># Referenz auf Vater-Objekt</span>
<span class="var">self</span>.<span class="attr">kinder</span>: <span class="fn">list</span>[<span class="fn">Person</span>] = [] <span class="cm"># Liste von Referenzen auf Kinder</span>
<span class="kw">def</span> <span class="fn">mutter_setzen</span>(<span class="var">self</span>, <span class="var">mutter</span>: <span class="str">'Person'</span>) -> <span class="kw">None</span>:
<span class="var">self</span>.<span class="attr">mutter</span> = <span class="var">mutter</span>
<span class="kw">if</span> <span class="var">self</span> <span class="kw">not in</span> <span class="var">mutter</span>.<span class="attr">kinder</span>:
<span class="var">mutter</span>.<span class="attr">kinder</span>.<span class="fn">append</span>(<span class="var">self</span>)
<span class="kw">def</span> <span class="fn">__str__</span>(<span class="var">self</span>) -> <span class="fn">str</span>:
<span class="kw">return</span> <span class="str">f"{self.name} (*{self.geburtsjahr})"</span></pre>
</div>
</section>
<!-- 4. Deine Aufgaben -->
<section class="card">
<h2>4. 🎯 Deine Aufgaben in <code>aufgabe.py</code></h2>
<p>Öffne die Datei <code>07_referenzen_und_speicher/aufgabe.py</code> und vervollständige die Stammbaum-Klasse:</p>
<ul class="task-list">
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t7_1">
<label for="t7_1" class="task-label">
<strong>TODO 1:</strong> <code>Person.__init__</code> mit <code>name</code>, <code>geburtsjahr</code>, <code>mutter=None</code>, <code>vater=None</code> und <code>kinder=[]</code>.
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t7_2">
<label for="t7_2" class="task-label">
<strong>TODO 2 & 3:</strong> <code>mutter_setzen</code> und <code>vater_setzen</code> (verknüpft Elternteil und fügt das Kind zur Kinderliste des Elternteils hinzu).
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t7_3">
<label for="t7_3" class="task-label">
<strong>TODO 4:</strong> <code>geschwister(self) -> list[Person]</code>: Findet alle Personen, die dieselbe Mutter oder denselben Vater haben (aber nicht <code>self</code>!).
</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="t7_4">
<label for="t7_4" class="task-label">
<strong>TODO 5:</strong> <code>grosseltern(self) -> list[Person]</code>: Gibt eine Liste aller bekannten Großeltern zurück.
</label>
</li>
</ul>
<h3>💡 Lösungshinweise (Aufklappen bei Bedarf)</h3>
<details>
<summary>🔍 Tipp zu TODO 4 (Geschwister finden)</summary>
<div class="details-content">
<p>Gehe alle Kinder der Mutter und alle Kinder des Vaters durch. Achte darauf, dass du <code>kind is not self</code> prüfst, damit man nicht selbst als Geschwisterteil gelistet wird, und füge niemanden doppelt hinzu!</p>
</div>
</details>
<details>
<summary>🔍 Tipp zu TODO 5 (Großeltern finden)</summary>
<div class="details-content">
<div class="code-container">
<pre><span class="var">ge</span> = []
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">mutter</span>:
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">mutter</span>.<span class="attr">mutter</span>: <span class="var">ge</span>.<span class="fn">append</span>(<span class="var">self</span>.<span class="attr">mutter</span>.<span class="attr">mutter</span>)
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">mutter</span>.<span class="attr">vater</span>: <span class="var">ge</span>.<span class="fn">append</span>(<span class="var">self</span>.<span class="attr">mutter</span>.<span class="attr">vater</span>)
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">vater</span>:
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">vater</span>.<span class="attr">mutter</span>: <span class="var">ge</span>.<span class="fn">append</span>(<span class="var">self</span>.<span class="attr">vater</span>.<span class="attr">mutter</span>)
<span class="kw">if</span> <span class="var">self</span>.<span class="attr">vater</span>.<span class="attr">vater</span>: <span class="var">ge</span>.<span class="fn">append</span>(<span class="var">self</span>.<span class="attr">vater</span>.<span class="attr">vater</span>)
<span class="kw">return</span> <span class="var">ge</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>07_referenzen_und_speicher</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="../06_abschlussprojekt_tamagotchi/index.html" class="btn btn-secondary">&larr; Zurück zu Kapitel 06</a>
<a href="../index.html" class="btn">Zur Kursübersicht &rarr;</a>
</div>
</section>
</main>
</body>
</html>