Variablen, Referenzen, Speicheradressen — ein Blick hinter die Kulissen von Python und dynamischen Datentypen.
Nicht alle Programmiersprachen gehen gleich mit Speicher um. Python unterscheidet sich grundlegend von Sprachen wie C oder Java — aber was genau bedeutet das?
int x = 5; — x ist für immer intx = 5 → dann x = "Hallo" ✓In C oder Java ist ein Array ein zusammenhängender Speicherblock fester Größe.
int zahlen[5] = {1,2,3,4,5};
Das reserviert genau 5 × 4 Byte = 20 Byte im Speicher. Die Größe kann danach nicht geändert werden. Braucht man mehr Platz, muss manuell ein neues, größeres Array angelegt und der Inhalt kopiert werden.
Pythons Liste ist ein dynamisches Objekt — sie wächst und schrumpft automatisch.
Python-Variablen sind keine Behälter für Werte — sie sind Namen, die auf Objekte zeigen.
In Python ist sogar die Zahl 5 ein vollständiges Objekt mit Typ, Wert und ID.
id(x)Was passiert wirklich, wenn du a = 5 schreibst? Python legt ein int-Objekt im Heap an und speichert eine Referenz darauf unter dem Namen a.
id()Weise Variablen zu und beobachte die Speicheradressen. Ändere Werte und schau, was passiert.
Im Speichermodell (Modul 2) haben wir gesehen, wie b = a bei Integers funktioniert. Bei Listen verhält sich Python jedoch anders — und das führt zu einer der häufigsten Fehlerquellen.
b = a bei IntegersUnveränderlich — ein Integer-Objekt kann nach seiner Erstellung nicht verändert werden. a = 10 erzeugt ein neues Objekt, das alte bleibt unberührt.
b = a zeigen beide auf dasselbe Objekt. Sobald aber a = 10 ausgeführt wird, zeigt a auf ein neues Objekt — b bleibt beim alten.Veränderlich — das Listen-Objekt selbst kann verändert werden, ohne dass ein neues Objekt entsteht. b = a erzeugt daher einen Alias: beide Namen zeigen auf dasselbe Objekt.
b.append(4) aufruft, wird das Listenobjekt direkt im Heap verändert — nicht b selbst. Da a auf dasselbe Objekt zeigt, sieht a die Änderung sofort.🔬 Sieh den Unterschied selbst — vergleiche Integer- und Listen-Aliasing:
b = a verhält sich bei einer Liste genauso wie bei einem Integer — b wird unabhängig von a.
Nach a = [1,2,3]; b = a; a = [9,9,9] zeigt b noch auf [1,2,3].
a = [9,9,9] lässt a auf ein neues Listenobjekt zeigen. b bleibt beim alten Objekt. Achtung: anders wäre es bei a[0] = 9 — das würde das Objekt direkt verändern.Strings verhalten sich wie Listen — s += "!" hängt das Ausrufezeichen direkt an das bestehende String-Objekt an.
s += "!" erstellt ein neues String-Objekt. Das alte Objekt bleibt unverändert im Heap — nur s zeigt danach auf das neue.Tuples sind immutable — t = (1,2,3); t[0] = 9 wirft einen Fehler.
t[0] zum Lesen funktioniert, aber t[0] = 9 wirft einen TypeError. Tuples sind damit die „eingefrorene" Variante einer Liste.copy()copy.copy()Erstellt ein neues Listenobjekt mit denselben Elementen. Änderungen an der Kopie beeinflussen das Original nicht — und umgekehrt.
import copy
a = [10, 20, 30]
b = copy.copy(a) # neues Objekt!
b.append(40)
print(a) # [10, 20, 30] ← unverändert
print(b) # [10, 20, 30, 40]
Kurzschreibweise: Statt copy.copy(a) geht auch a[:] oder list(a) — beides erzeugt ebenfalls eine flache Kopie.
🔬 Überprüfe deine Vorhersage: Was gibt der Code aus?
copy() reicht nichtBei Listen-in-Listen kopiert copy() nur die äußere Liste. Die inneren Listen werden weiterhin geteilt.
a = [1, [2, 3]]
b = copy.copy(a)
b[1].append(99)
print(a) # [1, [2, 3, 99]] ← !!!
Die äußere Liste ist neu — aber a[1] und b[1] zeigen noch auf dasselbe innere Listen-Objekt.
deepcopy()Kopiert alles rekursiv — auch alle inneren Objekte. Original und Kopie sind vollständig unabhängig.
a = [1, [2, 3]]
b = copy.deepcopy(a)
b[1].append(99)
print(a) # [1, [2, 3]] ← unberührt
Wann nötig? Immer bei verschachtelten Strukturen (Listen in Listen usw.) wenn beide Seiten unabhängig sein sollen.
🔬 Sieh selbst: Wo macht copy() den Unterschied?
Du kennst die wichtigsten Operationen bereits — jetzt verbindest du sie mit dem Speichermodell. Was passiert intern, wenn du append() oder insert() aufrufst?
list.append(x)
list.insert(i, x)
list.pop(i)
list.remove(x)
list.index(x)
len(list)
list.extend(l)
list.sort()
list.reverse()
list.count(x)
Experimentiere mit Listenoperationen. Versuche z.B. sys.getsizeof() um zu sehen, wie sich der Speicherbedarf einer Liste beim Wachsen verändert.
8 Fragen in vier Schwierigkeitsstufen — von Grundwissen bis kritischem Denken.
„In Python zeigen Variablen nicht auf Werte — sie zeigen auf Objekte. Das ist kein Fehler im Design, sondern eine bewusste Entscheidung für Effizienz und Flexibilität."