8. Das Datenmodell von Python

In Python funktionieren Variablen mehr wie in Sprachen der Lisp-Familie, was sich deutlich von dem unterscheidet, was ihr von C, Pascal oder ähnlichem gewöhnt sein mögt.

Die beste Vorstellung ist zunächst, dass in einem großen Raum alle Zahlen, Strings usf. bereits vorhanden sind und eine Zuweisung lediglich die Verbindung zwischen einem Namen und dem Wert herstellt – eine Referenz. In diesem Bild haben die Anweisungen

>>> s = "aaa"
>>> i = 2

folgenden Effekt:

In dieser Grafik stehen oben ein paar der (unendlichen vielen) Werte, die so im “Python-Universum” umherschwirren – ein paar Strings, darunter natürlich auch die Universelle Erklärung der Menschenrechte, ein paar Zahlen. Unten stehen dann die Namen, die schon definiert wurden – sie sind nicht eigentlich Teil des Python-Universums, sondern bilden einen eigenen Raum, den Namensraum oder Namespace.

Da Namen nicht im Python-Universum, sondern quasi im Hyperraum leben, gibt es auch kein Python-Konstrukt, das erlauben würde, Referenzen auf Namen zu bekommen (allerdings kann man Namen ins hoch ins Universum schaffen und geeignete Werte aus dem Universum zu Namen machen – wir werden so etwas später als Introspektion kennenlernen).

i = i+1

bewirkt jetzt Folgendes:

Gepunktet ist der Zustand vor der Zuweisung eingezeichnet.

Später sehr wichtig wird der Effekt von

k = i

– nämlich:

– k teilt den Wert von i. Es gibt keine “neue” Drei. Solange wir Werte nicht verändern können, ist das aber nicht schlimm.

Man Namen auch wieder löschen. Dazu gibt es das reservierte Wort del. Del operiert beispielsweise so:

>>> i = 2
>>> k = i
>>> k
2
>>> del k
>>> k
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'k' is not defined

Beachtet: Wir haben die Referenz k gelöscht, aber natürlich nicht den Wert 2:

>>> i
2

Auf der positiven Seite muss man in Python nur selten wirklich mal Namen löschen. del löscht allerdings allgemein Referenzen, und diese Eigenschaft wird uns bei der Manipulation von Sequenzen und Mappings nützlich sein.

(Weiterführend:) In Wirklichkeit sind die Verhältnisse natürlich etwas komplizierter als unser simples Modell mit dem Python-Universum es scheinen lässt. Es ist klar, dass ein Rechner mit endlichem Speicher nicht unendlich viele Werte in seinem Speicher halten kann, ganz abgesehen von der Frage, wie diese eigentlich erzeugt werden. Deshalb stellt Python die meisten Werte quasi on the fly her, wenn sie gebraucht werden und wirft sie wieder weg, wenn sie nicht mehr gebraucht werden (also keine Referenz mehr auf sie verweist). Dabei kann es unter Umständen auch mal zu Überproduktion kommen.

(Weiterführend:) Um sich das anzusehen, könnt ihr die eingebaute Python-Funktion id verwenden. Diese gibt eine eindeutige “Kennung” eines Wertes zurück, mit der sich die einzelnen Objekte des Python-Universums unterscheiden lassen. Unter Python 2.3 passiert dabei etwa so etwas:

>>> a = "bla"
>>> b = "bla"
>>> id(a)
1076955040
>>> id(b)
1076955040
>>> c = "b"+"la"
>>> id(c)
1076954912
>>> a==c
True
>>> a is c
False
>>> a is b
True

(Weiterführend:) Hier war Python also schlau genug, bei der Zuweisung von b zu merken, dass es "bla" schon erzeugt hat und verwendet diesen Wert weiter. Bei der Zuweisung von c hat das aber nicht geklappt, im Python-Universum wohnt jetzt zwei Mal der Wert "bla" – allerdings so ununterscheidbar wie eineiige Zwillinge, deshalb ist auch a == c. Es gibt aber einen Operator, der nachsieht, ob die Werte nicht nur gleich aussehen, sondern auch gleich sind: is. Wir werden später noch sehen, wozu das gut sein kann. Bis dahin sind all die Referenzfragen ziemlich akademisch; die Frage der Identität von Strings ist im Rahmen des hier behandelten Materials völlig irrelevant, zumal es sich dabei um ein “Implementierungsdetail” handelt, der Sprachstandard macht keine Aussagen, ob nach obigem Code a is c wahr sei oder nicht. Code, der sich auf ein bestimmtes Verhalten verlässt, wird in späteren Versionen von Python sehr wahrscheinlich nicht mehr funktionieren. Das, was oben beschrieben wurde (das “idealisierte” Python-Universum) reicht für alle unsere Betrachtungen aus und hat letztlich mehr “Wahrheit” als die harte Realität in diesen Ausführungen.

Und nochmal sei betont, dass die meisten Sprachen, mit denen ihr in der Schule Kontakt gehabt haben könntet, diese Sachen ganz anders machen.

Die Katze auf der Terrasse

Eine Folge dieser Logik ist, dass Werte in Python nicht wirklich Namen haben – Namen sind an Werte gebunden, nicht umgekehrt. Eine schöne Illustration davon ist folgendes Gleichnis, das auf den effbot (Frederik Lundh) zurückgeht:

Mit Python-Objekten ist es wie mir der Katze, die du irgendwann schlafend auf deiner Terrasse vorfindest. Ganz wie ein Python-Objekt kann dir die Katze nicht sagen, wie sie heißt – es ist ihr auch ganz egal. Um ihren Namen herauszufinden, wirst du wohl deine Nachbarn fragen müssen, und du solltest nicht überrascht sein, wenn du herausbekommst, dass die Katze viele Namen hat.

Die Nachbarn, die man nach den Namen der Katze fragen kann, sind genau die Namespaces – es ist durchaus möglich, dass ein und dasselbe Objekt in verschiedenen Namespaces verschiedene Namen hat.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Malt für die folgende Sequenz von Python-Anweisungen passende Ausschnitte des (idealisierten) Python-Universums, in die die dann aktiven Referenzen eingezeichnet sind.

>>> a = 3
>>> b = 0
>>> c = a
>>> d = a-c
>>> e = 2.71
>>> f = int(e/e)


Markus Demleitner

Copyright Notice