Ein Tupel ist eine unveränderliche Sammlung von Elementen in einer Sequenz.
Wie die meisten Sammlungen (siehe die eingebauten list, dict und set) können tuples jeden (oder mehrere) Datentyp(en) enthalten, einschließlich anderer tuples.
Die Elemente eines Tupels kannst du mit dem Konstrukt for item in <tuple> durchlaufen.
Wenn sowohl Index als auch Wert eines Elements benötigt werden, kannst du for index, item in enumerate(<tuple>) verwenden.
Wie bei jeder Sequenz kannst du auf Elemente in tuples über die Klammernotation zugreifen, indem du von links eine Zahl mit 0-based index oder von rechts eine Zahl mit -1-based index verwendest.
Tupel können vollständig oder teilweise über die Slice-Notation oder <tuple>.copy() kopiert werden und unterstützen alle allgemeinen Sequenzoperationen.
Da sie unveränderlich sind, unterstützen tuples keine Operationen auf veränderlichen Sequenzen.
Tupel belegen im Vergleich zu anderen Sammlungstypen sehr wenig Speicher und haben bei Zugriff über einen Index eine konstante Zugriffszeit (O(1)).
Sie können jedoch nicht in ihrer Größe geändert, sortiert oder nach der Erstellung verändert werden und sind daher weniger flexibel, wenn Daten häufig geändert oder aktualisiert werden müssen.
Wenn häufige Aktualisierungen oder Erweiterungen erforderlich sind, ist eine list, ein collections.deque oder ein array.array möglicherweise die bessere Datenstruktur.
Tupel können auf verschiedene Arten erstellt werden, entweder mit dem Konstruktor der Klasse tuple oder mit der Deklaration (<element_1>, <element_2>) (tuple-Literal).
tuple()-Konstruktor leer oder mit einem Iterable verwenden:>>> no_elements = tuple()
()
# The constructor *requires* an iterable, so single elements must be passed in a list or another tuple.
>>> one_element = tuple([16])
(16,)
Strings sind iterierbar. Wenn du also einen einzelnen str als Argument an den tuple()-Konstruktor übergibst, kann das überraschende Ergebnisse liefern:
# String elements (characters) are iterated through and added to the tuple
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')
Bei anderen Iterables werden die Elemente ebenfalls einzeln hinzugefügt:
>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)
>>> multiple_elements_set = tuple({2, 3, 5, 7, 11})
(2,3,5,7,11)
Ein dict wird standardmäßig über seine Schlüssel iteriert.
Um sowohl Schlüssel als auch Werte in ein Tupel aus einem Dictionary aufzunehmen, verwende <dict>.items(). Das gibt einen Iterator von (key, value)-tuples zurück.
>>> source_data = {"fish": "gold", "monkey": "brown"}
>>> multiple_elements_dict_1 = tuple(source_data)
('fish', 'monkey')
>>> multiple_elements_dict_2 = tuple(source_data.items())
(('fish', 'gold'), ('monkey', 'brown'))
Da der tuple()-Konstruktor nur Iterables (oder nichts) als Argumente akzeptiert, ist es viel einfacher, ein Ein-Element-Tupel über die Literal-Schreibweise zu erstellen.
>>> no_elements = ()
()
>>> one_element = ("Guava",)
("Guava",)
Beachte, dass Klammern im Allgemeinen nicht erforderlich sind, um ein tuple-Literal zu erstellen, sondern nur Kommas.
In den meisten Fällen gilt (<element_1>, <element_2>) jedoch als lesbarer.
Klammern sind auch in Fällen erforderlich, in denen es zu Mehrdeutigkeiten kommen kann, etwa bei einem leeren Tupel oder einem Tupel mit einem Element oder wenn eine Funktion ein Tupel als Argument erwartet.
>>> elements_separated_with_commas = "Parrot", "Bird", 334782
("Parrot", "Bird", 334782)
>>> elements_with_commas_and_parentheses = ("Triangle", 60, 60, 60)
("Triangle", 60, 60, 60)
Andere Datenstrukturen können als Elemente eines tuple aufgenommen werden, auch andere tuples.
>>> nested_data_structures = ({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
>>> nested_data_structures_1 = (["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
(["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
Tupel können mit dem Plus-Operator + verkettet werden. Dabei wird jedes tuple entpackt und ein neues, kombiniertes tuple erstellt.
>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")
#likewise, using the multiplication operator * is the equivalent of using + n times
>>> first_group = ("cat", "dog", "elephant")
>>> multiplied_group = first_group * 3
('cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant')
Auf Elemente in Tupeln (wie bei den anderen Sequenztypen str und list) kannst du über die Klammernotation zugreifen.
Indizes können von left → right (bei null beginnend) oder von right → left (bei -1 beginnend) laufen.
Tupel können auch vollständig oder teilweise über die Slice-Notation oder mit <tuple>.copy() kopiert werden.
>>> student_info = ("Alyssa", "grade 3", "female", 8)
#name is at index 0 or index -4
>>> student_name = student_info[0]
Alyssa
>>> student_name = student_info[-4]
Alyssa
#age is at index 3 or index -1
>>> student_age_1 = student_info[3]
8
>>> student_age_2 = student_info[-1]
8
Elemente in Tupeln können in einer Schleife mit der Syntax for item in <tuple> durchlaufen werden.
Wenn sowohl Index als auch Wert benötigt werden, kannst du for index, item in enumerate(<tuple>) verwenden.
>>> student_info = ("Alyssa", "grade 3", "female", 8)
>>> for item in student_info:
... print(item)
...
Alyssa
grade 3
female
8
>>> for index, item in enumerate(student_info):
... print("Index is: " + str(index) + ", value is: " + str(item) + ".")
...
Index is: 0, value is: Alyssa.
Index is: 1, value is: grade 3.
Index is: 2, value is: female.
Index is: 3, value is: 8.
Tupel werden oft als Datensätze verwendet, die Daten enthalten, die organisatorisch oder konzeptionell homogen sind und als eine einzelne Informationseinheit behandelt werden, auch wenn die einzelnen Elemente heterogene Datentypen haben.
>>> student_info = ("Alyssa", "grade 3", "female", 8)
Tupel werden auch verwendet, wenn homogene unveränderliche Datensequenzen für die hashability, die Speicherung in einem set oder die Erstellung von Schlüsseln in einem Dictionary benötigt werden.
Beachte: Obwohl tuples in den meisten Fällen unveränderlich sind, können sie veränderbar werden, wenn eines ihrer Elemente einen veränderbaren Typ hat, da sie jede Datenstruktur oder jedes Objekt enthalten können.
Wenn du einen veränderbaren Datentyp in einem tuple verwendest, wird das umgebende tuple nicht hashbar.
>>> cmyk_color_map = {
(.69, .3, .48, .1) : ("Teal 700", (59, 178, 146), 0x3BB292),
(0, .5, 1, 0) : ("Pantone 151", (247, 127, 1), 0xF77F01),
(.37, .89, 0, .44) : ("Pantone 267", (89, 16, 142), 0x59108E),
(0, 1, .46, .45) : ("Pantone 228", (140, 0, 76), 0x8C004C)
}
>>> unique_rgb_colors = {
(59, 178, 146),
(247, 127, 1),
(89, 16, 142),
(140, 0, 76),
(76, 0, 140)
}
>>> teal_700 = hash((59, 178, 146))
>>> teal_700 = hash(("Pantone 228", [(140, 0, 76), 0x8C004C]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Tupel werden oft als Datensätze verwendet, aber auf die darin enthaltenen Daten kann nur über Position/Index zugegriffen werden.
Die Klasse namedtuple() im Modul collections erweitert die grundlegende Tupel-Funktionalität, sodass du auf Elemente über ihren Namen zugreifen kannst.
Darüber hinaus kannst du eine dataclass anpassen, um eine ähnliche Funktionalität mit benannten Attributen zu erhalten, allerdings mit Vor- und Nachteilen.