Datentyp-Hierarchie (Wiederholung)

Zu Deiner besseren Orientierung zeige ich hier nochmals die Datentyp-Hierarchie von Python. Die Zahlendatentypen, Wahrheitswerte und Listen haben wir den vorangegangenen Abschnitten behandelt. Jetzt widmen wir uns den Tupeln.

Python Datentyphierarchie
Datentyp-Hierarchie in Python

Tupel

Ein Tupel (tuple<) entspricht in seine Struktur einer Liste. Ein Tupel wird jedoch in runden statt eckigen Klammern notiert. Im Gegensatz zu Liste ist es nicht veränderbar.

Ein leeres Tupel wird als () notiert. Um ein einelementiges Tupel von einem Wert in Klammern unterscheiden zu können, ist in solchen Fällen ein zusätzliches Komma zu schreiben. (1,) ist ein einelementiges Tupel, welches lediglich die dezimale Ganzzahl 1 enthält. Ohne das Komma, (1), würde Python das als eine 1 in Klammern interpretieren.

Auf die einzelnen Elemente wird analog zu den Elementen einer Liste zugegriffen, mit dem Slicing-Operator, den eckigen Klammern.

Tupelzuweisung und Packing/Unpacking

Bei einer Tupelzuweisung werden mehrere Werte in einer einzigen Anweisung zugewiesen.
>>> a = 1
>>> b = 2
>>> c = 3
>>> # ist gleichbedeutend mit:
>>> a, b, c = 1, 2, 3

Weil zuerst die rechte Seite vom Zuweisungsoperator ausgewertet wird, bevor die Zuweisung an die links stehenden Variablen erfolgt, kann die Tupelzuweisung dazu verwendet werden, die Wertzuweisungen von Variablen zu tauschen. Ohne Tupelzuweisung ist dazu eine Hilfsvariable erforderlich.

>>> a, b = 1, 2
>>> hilfe = a
>>> a = b
>>> b = hilfe
>>> a
    2
>>> b
    1

Das funktioniert so, als wolltest Du den Inhalt zweier Gläser miteinander vertauschen. Dazu brauchst Du ein drittes Glas als Zwischenspeicher. Das ist die Rolle der Variablen hilfe.

Mit einer Tupelzuweisung kannst Du den Tausch kürzer formulieren:

>>> a, b = 1, 2
>>> a, b = b, a
>>> a
    2
>>> b
    1

Packing und Unpacking bezeichnen das Packen und Entpacken von Tupeln. Beim Packing wird aus einer kommaseparierten Sequenz von Werten automatisch ein Tupel erzeugt. Beim Unpacking wird es automatisch zu einer kommaseparierten Wertesequenz entpackt.

>>> heute = 21, 10, 2022
>>> heute
    (21, 10, 2022)
>>> tag, monat, jahr = heute
>>> tag
    21
>>> monat
    10
>>> jahr
    2022

Eine spezielle Form des Entpackens verwendet einen Astrisk, um mehrere Elemente einer Sequenz von Elementen zu adressieren. Vor und nach dem Asterisk-Sammelelement dürfen konkret bezeichnete Elemente stehen. Am Beispiel wird Dir das deutlich.

>>> tupel = (1, 2, 3, 4, 5, 6, 7, 8)
>>> erstes, *mittlere_elemente, letztes = tupel
>>> erstes
    1
>>> mittlere_elemente          # ACHTUNG: das ist eine Liste
    [2, 3, 4, 5, 6, 7]
>>> type(mittlere_elemente)
    <class 'list'>
>>> letztes
    8
>>> erstes, *rest = tupel
>>> erstes
    1
>>> rest
    [2, 3, 4, 5, 6, 7, 8]

Unveränderlich heißt nicht zwingend „absolut unveränderlich“

Ein Tupel ist unveränderlich. Wenn seine Elemente jedoch veränderlich sind, dann können sich deren Werte ändern, obgleich das Tupel formal unverändert bleibt.

>>> tupel = (1, [2])    # int (immutable), list[int] (mutable)
>>> tupel[0] = 2        # verboten!
    Traceback (most recent call last):
      File "<pyshell#62>", line 1, in <module>
        tupel[0] = 2        # verboten!
    TypeError: 'tuple' object does not support item assignment
>>> id(tupel[1])
    2326559376576
>>> tupel[1][0] = 2000  # erlaubt! - Liste ist veränderbar
>>> tupel
    (1, [2000])
>>> id(tupel[1])
    2326559376576

Die ID der Liste ist unverändert, weshalb das Tupel als solches unverändert ist. Die Referenz des Elements am Index 0 ist jedoch verändert.