Tupel in Python

Die Datenstruktur Tupel (engl.: Tuple) ist den Listen nicht unähnlich. Denn bei einem Tupel handelt es sich ebenfalls um einen sequenziellen Datentyp, der aber — im Gegensatz zu einer Liste — nicht veränderbar (immutable) ist.

Grundlagen

Ein leeres Tupel wird mit einem leeren Paar runder Klammern definiert:

my_tuple = ()

Einem Tupel können auch sogleich Werte zugewiesen werden. Dabei ist es auch möglich, die Klammern wegzulassen:

my_tuple = (4, 12, 7)  # mit Klammern
my_tuple = 4, 12, 7  # ohne Klammern

Die zugewiesenen Werte müssen nicht vom gleichen Datentyp sein:

my_tuple = ("Wiesbaden", "Hessen", "278342")

Und eine Zeile Code ist ausreichend, um die Werte drei Variablen zuzuweisen. Dies wird als tuple unpacking bezeichnet.

town, state, population = ("Wiesbaden", "Hessen", "278342")

Manchmal benötigt man nicht alle Werte eines Tupels. In diesem Fall kann ein Unterstrich (_) als Dummy gesetzt werden.

town, _, _ = ("Wiesbaden", "Hessen", "278342")

Darüber hinaus kann auch über den Index auf den Wert eines Tupels zugegriffen werden:

population = my_tuple[2]

Sind Tupel wirklich nicht veränderbar?

Bei dieser Frage handelt es sich eher um ein Thema für Fortgeschrittene, dass ich aber dennoch hier nicht ausblenden möchte. Worum geht es hierbei? Am Anfang dieses Blogbeitrags schrieb ich, dass Tupel nicht veränderbar seien. Das ist auch grundsätzlich richtig, denn der Versuch einen Wert zu ändern, führt zu einer Fehlermeldung:

numbers = (15, 22, 4)
numbers[0] = 16

Traceback (most recent call last):
  File "tuple_examples.py", line 39, in <module>
    numbers[0] = 16
TypeError: 'tuple' object does not support item assignment

Dies ist aber nur die halbe Wahrheit. Denn wie  Luciano Ramalho in seinem Buch Fluent Python zurecht anführt, muss man eher von einer relativen Unveränderbarkeit sprechen. Dies wird anhand folgenden Beispiels deutlich, einem Tupel, bei dem es sich bei einem Wert um eine Liste handelt.

my_values = ("Finnland", 47, [13, 27, 2])
print(id(my_values))
4542349376

Jetzt verändere ich den letzten Wert dieses Tupels, mithin die Liste [13, 27, 2].

my_values[2][2] = 21
print(id(my_values))
4542349376

Aufgrund der gleichen id steht fest, dass es sich um das identische Tupel my_values handelt. Nichtsdestotrotz unterscheiden sich jetzt die Werte des Tupels my_values im Vergleich zum ursprünglichen Tupel.

vorher: ("Finnland", 47, [13, 27, 2])
nachher: ("Finnland", 47, [13, 27, 21])

Dies erklärt sich dadurch, dass es sich bei einem Tupel um einen Container handelt, der Referenzen auf andere Objekte enthält. Oder anders ausgedrückt: Es sind nicht die Objekte selbst in dem Tupel-Container enthalten, sondern lediglich die Informationen zu diesen Objekten. Und die Referenzen bleiben tatsächlich unverändert. Insofern kann man sagen, dass ein Tupel nicht veränderbar ist. Wenn aber die Elemente eines Tupels selbst veränderbar sind, können sich die Werte des Tupels durchaus ändern (wie im Beispiel anhand einer veränderbaren Liste gezeigt).

Neben dem Tupel-Datentyp gibt es auch noch die namedtuple aus dem collections-Modul. In diesem Blogbeitrag werden sie kurz vorgestellt.