1. Was ist eine Referenz? (Variablen sind Namensschilder)
Viele glauben, eine Variable sei eine Box, in der das Objekt direkt drinliegt. In Python ist das anders: Eine Variable ist in Wirklichkeit ein Zeiger (eine Referenz) auf einen Bereich im Arbeitsspeicher (RAM).
b = a, baust du kein zweites Haus, sondern schreibst die gleiche Adresse einfach auf einen zweiten Zettel!
Das Phänomen: Was passiert bei b = a?
liste_a = [1, 2, 3] liste_b = liste_a # liste_b zeigt auf GENAU DIESELBE Liste im Speicher! liste_b.append(99) print(liste_a) # Ausgabe: [1, 2, 3, 99] <-- liste_a hat sich mitverändert!
STACK (Variablen-Namen) HEAP (Echter Speicher / RAM)
┌──────────────┐ ┌──────────────────────────────┐
│ liste_a ────┼──────────────────────>│ ID: 0x7ffd1a [1, 2, 3, 99] │
└──────────────┘ └──────────────────────────────┘
▲
┌──────────────┐ │
│ liste_b ────┼───────────────────────────────────────┘
└──────────────┘
(Beide Variablen zeigen auf denselben Pfeil im Heap!)
- Mutable (veränderlich): Listen, Dictionaries, eigene Klassenobjekte. Wenn du sie an einer Stelle änderst, ändern sich alle Variablen, die darauf zeigen!
- Immutable (unveränderlich): Zahlen (
int,float), Texte (str), Tupel (tuple). Beim Ändern wird automatisch ein neues Objekt im Speicher erzeugt.
2. Der Unterschied zwischen == und is
In Python gibt es zwei Arten von Vergleichen:
| Operator | Bedeutung | Frage im Hintergrund |
|---|---|---|
== |
Wertegleichheit | Haben beide Objekte denselben Inhalt? |
is |
Identität | Sind beide Variablen exakt dasselbe Objekt an derselben Speicheradresse? |
x = [1, 2, 3] y = [1, 2, 3] z = x print(x == y) # True (weil der Inhalt gleich ist) print(x is y) # False (zwei getrennte Listen im Speicher) print(x is z) # True (z zeigt direkt auf dieselbe Liste wie x)
3. Praxisbeispiel: Der Familienstammbaum 🌳
Warum sind Referenzen so genial? Weil ein und dasselbe Objekt in vielen Beziehungen vorkommen kann. Eine Person namens Susi ist gleichzeitig die Mutter von Erika, das Kind von Fritz und die Schwester von Tom.
class Person: def __init__(self, name: str, geburtsjahr: int): self.name: str = name self.geburtsjahr: int = geburtsjahr self.mutter: Person | None = None # Referenz auf Mutter-Objekt self.vater: Person | None = None # Referenz auf Vater-Objekt self.kinder: list[Person] = [] # Liste von Referenzen auf Kinder def mutter_setzen(self, mutter: 'Person') -> None: self.mutter = mutter if self not in mutter.kinder: mutter.kinder.append(self) def __str__(self) -> str: return f"{self.name} (*{self.geburtsjahr})"
4. 🎯 Deine Aufgaben in aufgabe.py
Öffne die Datei aufgabe.py und vervollständige die Stammbaum-Klasse:
💡 Lösungshinweise (Aufklappen bei Bedarf)
🔍 Tipp zu TODO 4 (Geschwister finden)
Gehe alle Kinder der Mutter und alle Kinder des Vaters durch. Achte darauf, dass du kind is not self prüfst, damit man nicht selbst als Geschwisterteil gelistet wird, und füge niemanden doppelt hinzu!
🔍 Tipp zu TODO 5 (Großeltern finden)
ge = [] if self.mutter: if self.mutter.mutter: ge.append(self.mutter.mutter) if self.mutter.vater: ge.append(self.mutter.vater) if self.vater: if self.vater.mutter: ge.append(self.vater.mutter) if self.vater.vater: ge.append(self.vater.vater) return ge
5. 🧪 Lösung überprüfen
Führe im Terminal im Ordner 07_referenzen_und_speicher folgenden Befehl aus:
python3 test_aufgabe.py