14.6. Tupel - tuple#
Listen und Tupel tuple
(wie auch Zeichenketten, und Zahlenbereiche) sind allesamt Sequenzen und haben dadurch sehr ähnliche Eigenschaften.
Einzig bei der Erstellung verwenden wir statt der eckigen die runden Klammern:
numbers = (1, 2, 3, 4, 5)
numbers
(1, 2, 3, 4, 5)
Die Indexierung ist identisch zur Indexierung von Listen.
numbers = (1, 2, 3, 4, 5)
print(numbers[2:4])
(3, 4)
Der große Unterschied lieft in der Veränderbarkeit, denn Tupel tuple
sind unveränderlich (engl. immutable)!
Unveränderlichkeit
Im Gegensatz zu Listen sind Tupel unveränderliche Datenstrukturen.
Aber Vorsicht ist geboten, denn das bedeutet nicht, dass wir ein Tupel überhaupt nicht verändern können.
Was wir jedoch nicht verändern können sind die Adressen bzw. id
s seiner Elemente!
Folgender Code führt zu einem Fehler:
numbers = (1, 2, 3, 4, 5)
numbers[2] = -10
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 2
1 numbers = (1, 2, 3, 4, 5)
----> 2 numbers[2] = -10
TypeError: 'tuple' object does not support item assignment
Doch können wir eine Datenstruktur, die Element eines Tupels ist, durchaus verändern:
numbers = (1, 2, [3, 4, 5])
numbers[2][0] = 'a'
numbers
(1, 2, ['a', 4, 5])
Tupel werden oft verwendet wenn wir eine Ansammlung von heterogenen Datentypen zusammenfassen wollen, und wir explizit ausdrücken bzw. sicher gehen wollen, dass dieses Tupel nicht verändert wird.
Um beispielsweise das sich nicht ändernde Alphabet zu modellieren, eignet sich ein Tupel:
alphabet = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')
alphabet
('A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z')
Python
bietet eine etwas hässliche Abkürzung für die Erstellung eines Tupels mit nur einem Element:
singleton = 1,
singleton
(1,)
entspricht
singleton = (1,)
singleton
(1,)
Achtung
number = (1)
number
1
funktioniert nicht!
Python
bietet auch das Konzept des tuple-packing und tuple-unpacking, was enorm praktisch ist:
triple = (1, 2, 3)
x, y, z = triple # unpacking
print(f'x = {x}')
print(f'y = {y}')
print(f'z = {z}')
packing = x, y, z # packing
print(f'packing = {packing}')
x = 1
y = 2
z = 3
packing = (1, 2, 3)
Ziemlich cool, wie wir finden. Packing bzw. unpacking ist insbesondere praktisch, wenn Sie eine Funktion schreiben möchten, die mehr als ein Rückgabewert hat:
import random as rnd
def random_rgb_color():
r = rnd.randint(0, 255)
g = rnd.randint(0, 255)
b = rnd.randint(0, 255)
return r, g, b
r, g, b = random_rgb_color()
print(f'red = {r}, green = {g}, blue = {b}')
red = 187, green = 61, blue = 238
Im Falle der Listen hat der +=
-Operator die Liste verändert.
Was glauben Sie macht der +=
-Operator für Tupel?
Ist er definiert?
Testen wir es aus:
numbers = (1, 2, 3, 4, 5)
numbers += (6,7,8)
numbers
(1, 2, 3, 4, 5, 6, 7, 8)
Kein Fehler!
Wird nun doch numbers
verändert?
Ja und nein.
Der Speicherbereich des ursprünglichen Tupels bleibt unverändert, stattdessen wird eine Kopie angelegt.
numbers = (1, 2, 3, 4, 5)
numbers_copy = numbers
print(f'id before += {id(numbers)}')
numbers += (6,7,8)
print(f'id after += {id(numbers)}')
print(f'id after += of the original {id(numbers_copy)}')
print(f'numbers: {numbers}')
print(f'numbers_copy: {numbers_copy}')
id before += 4413008656
id after += 4420433344
id after += of the original 4413008656
numbers: (1, 2, 3, 4, 5, 6, 7, 8)
numbers_copy: (1, 2, 3, 4, 5)
Diese Inkonsistenz kann gefährlich sein, denn obwohl die Syntax der Listenverkettung und Tupelverkettung sehr ähnlich sind, ist ihre Semantik sehr verschieden.
(Effizienzbetrachtung von Tupeln und Listen)
Welche der folgenden Code-Teile benötigt nach Ihrer Meinung mehr Computerressourcen und warum?
Listenerzeugung durch Anhängen:
numbers = []
i = 0
while i < 100:
numbers += [i]
i += 1
numbers
Tupelerzeugung durch Anhängen:
numbers = tuple()
i = 0
while i < 100:
numbers += (i,)
i += 1
numbers
Solution to Exercise 14.3 (Effizienzbetrachtung von Tupeln und Listen)
Die Tupelerzeugung durch Anhängen ist deutlich langsamer und speicherintensiver, denn bei jeder Konkatenation +=
wird numbers
im Speicher kopiert.
Der Code erzeugt damit 100 unterschiedliche Tupel!
Im Fall der Liste wird einfach nur ein Element hinten dran gehängt.