Sets und Tuples in Python
Lerne alles über Tuples und Sets in Python: unveränderliche Sequenzen, einzigartige Sammlungen, Mengenoperationen und wann du welche Datenstruktur verwendest.
Sets und Tuples in Python
Neben Listen und Dictionaries gibt es in Python zwei weitere wichtige Datenstrukturen: Tuples (unveränderliche Listen) und Sets (Mengen mit einzigartigen Elementen). In diesem Tutorial lernst du, wann und wie du diese Strukturen effektiv einsetzt.
Tuples: Unveränderliche Listen
Ein Tuple ist wie eine Liste, aber unveränderbar (immutable). Einmal erstellt, können keine Elemente hinzugefügt, entfernt oder geändert werden.
Tuple erstellen
# Mit runden Klammern
koordinaten = (10, 20)
farben = ("rot", "grün", "blau")
gemischt = (42, "Hallo", True, 3.14)
# Ohne Klammern (auch gültig, aber weniger lesbar)
punkt = 5, 10
print(punkt) # (5, 10)
print(type(punkt)) # <class 'tuple'>
# Mit dem tuple()-Konstruktor
aus_liste = tuple([1, 2, 3])
aus_string = tuple("Python")
print(aus_string) # ('P', 'y', 't', 'h', 'o', 'n')
# Leeres Tuple
leer = ()
auch_leer = tuple()
# ACHTUNG: Tuple mit einem Element braucht ein Komma!
kein_tuple = (42) # Das ist nur eine Zahl!
print(type(kein_tuple)) # <class 'int'>
ein_element = (42,) # DAS ist ein Tuple
print(type(ein_element)) # <class 'tuple'>
# Oder ohne Klammern:
auch_tuple = 42,
print(type(auch_tuple)) # <class 'tuple'>
Auf Tuple-Elemente zugreifen
fruechte = ("Apfel", "Banane", "Kirsche", "Dattel")
# Indizierung (wie bei Listen)
print(fruechte[0]) # Apfel
print(fruechte[-1]) # Dattel
print(fruechte[1:3]) # ('Banane', 'Kirsche')
# Tuple-Methoden
print(fruechte.count("Banane")) # 1
print(fruechte.index("Kirsche")) # 2
print(len(fruechte)) # 4
# Prüfen, ob Element vorhanden
print("Apfel" in fruechte) # True
# ABER: Verändern ist NICHT möglich!
# fruechte[0] = "Mango" # TypeError: 'tuple' object does not support item assignment
# fruechte.append("Mango") # AttributeError: 'tuple' object has no attribute 'append'
Tuple Unpacking
Eine der nützlichsten Funktionen von Tuples ist das Unpacking (Entpacken):
# Einfaches Unpacking
koordinaten = (10, 20, 30)
x, y, z = koordinaten
print(x) # 10
print(y) # 20
print(z) # 30
# Variablen tauschen (ohne temporäre Variable!)
a = 5
b = 10
a, b = b, a
print(a, b) # 10 5
# Funktion mit mehreren Rückgabewerten
def min_max(zahlen):
return min(zahlen), max(zahlen)
kleinste, groesste = min_max([3, 1, 7, 2, 9])
print(f"Min: {kleinste}, Max: {groesste}") # Min: 1, Max: 9
# Extended Unpacking mit *
erste, *rest = (1, 2, 3, 4, 5)
print(erste) # 1
print(rest) # [2, 3, 4, 5] (als Liste!)
erste, *mitte, letzte = (1, 2, 3, 4, 5)
print(erste) # 1
print(mitte) # [2, 3, 4]
print(letzte) # 5
# Unpacking in Schleifen
punkte = [(1, 2), (3, 4), (5, 6)]
for x, y in punkte:
print(f"x={x}, y={y}")
# Unpacking mit enumerate
namen = ["Anna", "Ben", "Clara"]
for index, name in enumerate(namen):
print(f"{index}: {name}")
Wann Tuples statt Listen?
Verwende Tuples, wenn:
# 1. Daten sich nicht ändern sollen (Schutz vor Veränderung)
WOCHENTAGE = ("Montag", "Dienstag", "Mittwoch", "Donnerstag",
"Freitag", "Samstag", "Sonntag")
# 2. Als Dictionary-Schlüssel (Listen können das nicht!)
standorte = {
(52.52, 13.405): "Berlin",
(48.137, 11.576): "München",
(50.938, 6.957): "Köln"
}
print(standorte[(52.52, 13.405)]) # Berlin
# 3. Für Funktionsrückgaben mit mehreren Werten
def teile(a, b):
quotient = a // b
rest = a % b
return quotient, rest # Gibt ein Tuple zurück
ergebnis = teile(17, 5)
print(ergebnis) # (3, 2)
q, r = teile(17, 5) # Direkt entpacken
# 4. Tuples sind schneller und verbrauchen weniger Speicher
import sys
liste = [1, 2, 3, 4, 5]
tupel = (1, 2, 3, 4, 5)
print(sys.getsizeof(liste)) # z.B. 120 Bytes
print(sys.getsizeof(tupel)) # z.B. 80 Bytes
Named Tuples
Für bessere Lesbarkeit kannst du Named Tuples verwenden:
from collections import namedtuple
# Named Tuple definieren
Punkt = namedtuple("Punkt", ["x", "y"])
Farbe = namedtuple("Farbe", "rot gruen blau")
# Instanzen erstellen
p1 = Punkt(10, 20)
p2 = Punkt(x=30, y=40)
rot = Farbe(255, 0, 0)
# Zugriff über Namen (lesbar!) oder Index
print(p1.x) # 10
print(p1.y) # 20
print(p1[0]) # 10 (auch per Index)
print(rot.rot) # 255
# Named Tuples sind immer noch Tuples
print(isinstance(p1, tuple)) # True
# Nützliche Methoden
print(p1._asdict()) # {'x': 10, 'y': 20}
p3 = p1._replace(x=50)
print(p3) # Punkt(x=50, y=20) -- neues Tuple!
# Praxis-Beispiel: Studentendaten
Student = namedtuple("Student", ["name", "alter", "fach", "note"])
studenten = [
Student("Anna", 22, "Informatik", 1.3),
Student("Ben", 24, "Mathematik", 2.0),
Student("Clara", 21, "Physik", 1.7)
]
for s in studenten:
print(f"{s.name} ({s.alter}): {s.fach}, Note {s.note}")
# Besten Studenten finden
beste = min(studenten, key=lambda s: s.note)
print(f"\nBeste Note: {beste.name} mit {beste.note}")
Sets: Einzigartige Elemente
Ein Set ist eine ungeordnete Sammlung von einzigartigen Elementen. Duplikate werden automatisch entfernt.
Set erstellen
# Mit geschweiften Klammern
farben = {"rot", "grün", "blau"}
print(farben) # {'rot', 'blau', 'grün'} (Reihenfolge kann variieren!)
# Duplikate werden automatisch entfernt
zahlen = {1, 2, 3, 2, 1, 4, 3}
print(zahlen) # {1, 2, 3, 4}
# Mit dem set()-Konstruktor
aus_liste = set([1, 2, 3, 2, 1])
print(aus_liste) # {1, 2, 3}
aus_string = set("Mississippi")
print(aus_string) # {'M', 'i', 's', 'p'}
# ACHTUNG: Leeres Set NUR mit set()!
leeres_set = set() # Leeres Set
leeres_dict = {} # Leeres DICTIONARY, KEIN Set!
print(type(leeres_set)) # <class 'set'>
print(type(leeres_dict)) # <class 'dict'>
Set-Operationen (Mengenoperationen)
Sets unterstützen mathematische Mengenoperationen:
python_devs = {"Anna", "Ben", "Clara", "David"}
java_devs = {"Clara", "David", "Eva", "Frank"}
# Vereinigung (Union) -- alle aus beiden Sets
alle = python_devs | java_devs
# ODER: alle = python_devs.union(java_devs)
print(alle)
# {'Anna', 'Ben', 'Clara', 'David', 'Eva', 'Frank'}
# Schnittmenge (Intersection) -- nur gemeinsame
gemeinsam = python_devs & java_devs
# ODER: gemeinsam = python_devs.intersection(java_devs)
print(gemeinsam) # {'Clara', 'David'}
# Differenz -- nur in der ersten, nicht in der zweiten
nur_python = python_devs - java_devs
# ODER: nur_python = python_devs.difference(java_devs)
print(nur_python) # {'Anna', 'Ben'}
nur_java = java_devs - python_devs
print(nur_java) # {'Eva', 'Frank'}
# Symmetrische Differenz -- in einer, aber nicht in beiden
entweder_oder = python_devs ^ java_devs
# ODER: entweder_oder = python_devs.symmetric_difference(java_devs)
print(entweder_oder) # {'Anna', 'Ben', 'Eva', 'Frank'}
# Teilmenge und Obermenge prüfen
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
print(a.issubset(b)) # True (a ist Teilmenge von b)
print(a <= b) # True (gleicher Operator)
print(b.issuperset(a)) # True (b ist Obermenge von a)
print(b >= a) # True
# Disjunkt prüfen (keine gemeinsamen Elemente)
c = {6, 7, 8}
print(a.isdisjoint(c)) # True
print(a.isdisjoint(b)) # False
Elemente hinzufügen und entfernen
mein_set = {1, 2, 3}
# Ein Element hinzufügen
mein_set.add(4)
print(mein_set) # {1, 2, 3, 4}
# Bereits vorhandenes Element hinzufügen (kein Fehler!)
mein_set.add(3)
print(mein_set) # {1, 2, 3, 4} -- keine Änderung
# Mehrere Elemente hinzufügen
mein_set.update([5, 6, 7])
print(mein_set) # {1, 2, 3, 4, 5, 6, 7}
# Element entfernen (wirft KeyError, wenn nicht vorhanden)
mein_set.remove(3)
print(mein_set) # {1, 2, 4, 5, 6, 7}
# mein_set.remove(99) # KeyError!
# Element sicher entfernen (kein Fehler, wenn nicht vorhanden)
mein_set.discard(99) # Kein Fehler
mein_set.discard(2)
print(mein_set) # {1, 4, 5, 6, 7}
# Beliebiges Element entfernen und zurückgeben
element = mein_set.pop()
print(f"Entfernt: {element}")
# Set leeren
mein_set.clear()
print(mein_set) # set()
frozenset
Ein frozenset ist ein unveränderliches Set:
# frozenset erstellen
unveraenderlich = frozenset([1, 2, 3, 4])
# Lesen funktioniert wie bei normalen Sets
print(3 in unveraenderlich) # True
print(len(unveraenderlich)) # 4
# Mengenoperationen funktionieren
a = frozenset([1, 2, 3])
b = frozenset([3, 4, 5])
print(a | b) # frozenset({1, 2, 3, 4, 5})
print(a & b) # frozenset({3})
# ABER: Verändern ist nicht möglich!
# unveraenderlich.add(5) # AttributeError
# unveraenderlich.remove(1) # AttributeError
# Vorteil: Kann als Dictionary-Schlüssel oder in Sets verwendet werden
mein_dict = {frozenset([1, 2]): "Paar"}
mein_set = {frozenset([1, 2]), frozenset([3, 4])}
Praxis: Duplikate entfernen
# Einfachster Weg, Duplikate zu entfernen
zahlen = [1, 3, 2, 3, 1, 4, 2, 5, 3]
eindeutig = list(set(zahlen))
print(eindeutig) # [1, 2, 3, 4, 5] (Reihenfolge nicht garantiert!)
# Duplikate entfernen UND Reihenfolge beibehalten
def ohne_duplikate(liste):
gesehen = set()
ergebnis = []
for element in liste:
if element not in gesehen:
gesehen.add(element)
ergebnis.append(element)
return ergebnis
print(ohne_duplikate([1, 3, 2, 3, 1, 4, 2]))
# [1, 3, 2, 4] -- Reihenfolge beibehalten!
# Gemeinsame und unterschiedliche Elemente finden
liste_a = [1, 2, 3, 4, 5]
liste_b = [4, 5, 6, 7, 8]
gemeinsam = set(liste_a) & set(liste_b)
print(f"Gemeinsam: {gemeinsam}") # {4, 5}
nur_a = set(liste_a) - set(liste_b)
print(f"Nur in A: {nur_a}") # {1, 2, 3}
nur_b = set(liste_b) - set(liste_a)
print(f"Nur in B: {nur_b}") # {6, 7, 8}
alle = set(liste_a) | set(liste_b)
print(f"Alle zusammen: {alle}") # {1, 2, 3, 4, 5, 6, 7, 8}
Praxis: Mengenvergleiche
# Kursanmeldungen vergleichen
kurs_python = {"Anna", "Ben", "Clara", "David", "Eva"}
kurs_datenbanken = {"Clara", "Eva", "Frank", "Gina"}
kurs_webdev = {"Anna", "David", "Frank", "Hannah"}
# Wer besucht Python UND Datenbanken?
print("Python + DB:", kurs_python & kurs_datenbanken)
# {'Clara', 'Eva'}
# Wer besucht mindestens einen Kurs?
alle_studenten = kurs_python | kurs_datenbanken | kurs_webdev
print(f"Alle Studenten: {len(alle_studenten)}")
print(alle_studenten)
# Wer besucht NUR Python?
nur_python = kurs_python - kurs_datenbanken - kurs_webdev
print(f"Nur Python: {nur_python}") # {'Ben'}
# Wer besucht alle drei Kurse?
alle_drei = kurs_python & kurs_datenbanken & kurs_webdev
print(f"Alle drei Kurse: {alle_drei}") # set() -- niemand
# Wer besucht genau zwei Kurse?
# (in mindestens zwei, aber nicht in allen drei)
in_zwei = ((kurs_python & kurs_datenbanken) |
(kurs_python & kurs_webdev) |
(kurs_datenbanken & kurs_webdev)) - alle_drei
print(f"Genau in zwei Kursen: {in_zwei}")
Vergleichstabelle: List vs Tuple vs Set vs Dict
| Eigenschaft | List | Tuple | Set | Dict |
|---|---|---|---|---|
| Syntax | [1, 2, 3] | (1, 2, 3) | {1, 2, 3} | {"a": 1} |
| Veränderbar | Ja | Nein | Ja | Ja |
| Geordnet | Ja | Ja | Nein | Ja (ab 3.7) |
| Duplikate | Ja | Ja | Nein | Keys: Nein |
| Indizierung | Ja [0] | Ja [0] | Nein | Per Key ["a"] |
| Slicing | Ja | Ja | Nein | Nein |
| Suche (in) | O(n) langsam | O(n) langsam | O(1) schnell | O(1) schnell |
| Dict-Schlüssel | Nein | Ja | Nein* | — |
| Verwendung | Sammlungen | Konstanten | Einzigartige Werte | Zuordnungen |
*frozensets können als Dictionary-Schlüssel verwendet werden.
# Zusammenfassung der Erstellung
meine_liste = [1, 2, 3] # veränderbar, geordnet, Duplikate OK
mein_tuple = (1, 2, 3) # unveränderbar, geordnet, Duplikate OK
mein_set = {1, 2, 3} # veränderbar, ungeordnet, keine Duplikate
mein_dict = {"a": 1, "b": 2} # veränderbar, geordnet, Keys einzigartig
# Umwandlung zwischen Typen
zahlen = [1, 2, 3, 2, 1]
print(tuple(zahlen)) # (1, 2, 3, 2, 1)
print(set(zahlen)) # {1, 2, 3}
print(list(set(zahlen))) # [1, 2, 3]
Übungen
Übung 1: Tuple-Operationen
Erstelle ein Programm, das Koordinaten als Tuples verwaltet und die Distanz zwischen zwei Punkten berechnet.
import math
def distanz(punkt1, punkt2):
"""Berechne die euklidische Distanz zwischen zwei Punkten."""
# Deine Lösung hier
pass
# Test
p1 = (0, 0)
p2 = (3, 4)
print(distanz(p1, p2)) # 5.0
p3 = (1, 1)
p4 = (4, 5)
print(distanz(p3, p4)) # 5.0
Übung 2: Set-Operationen mit Wortschatz
Zwei Schüler lernen Vokabeln. Finde heraus, welche Wörter beide kennen, welche nur einer kennt, und welche sie zusammen kennen.
schueler_a = {"Hund", "Katze", "Haus", "Auto", "Baum", "Blume"}
schueler_b = {"Katze", "Blume", "Sonne", "Mond", "Baum", "Stern"}
# Deine Lösung hier:
# 1. Welche Wörter kennen beide?
# 2. Welche kennt nur Schüler A?
# 3. Welche kennt nur Schüler B?
# 4. Wie viele verschiedene Wörter kennen sie zusammen?
Übung 3: Named Tuple für Produkte
Erstelle ein Warenwirtschaftssystem mit Named Tuples.
from collections import namedtuple
# Definiere einen Named Tuple "Produkt" mit: name, preis, menge, kategorie
# Erstelle eine Liste von mindestens 5 Produkten
# Berechne:
# - Den Gesamtwert aller Produkte (preis * menge)
# - Das teuerste Produkt
# - Alle Produkte einer bestimmten Kategorie
Übung 4: Anagramm-Prüfer
Schreibe eine Funktion, die prüft, ob zwei Wörter Anagramme sind (gleiche Buchstaben, andere Reihenfolge).
def ist_anagramm(wort1, wort2):
# Deine Lösung hier (verwende Sets und/oder Sortierung)
pass
# Tests
print(ist_anagramm("listen", "silent")) # True
print(ist_anagramm("hallo", "welt")) # False
print(ist_anagramm("Erde", "Rede")) # True
Pro-Tipp: Verwende Set Comprehensions fuer kompakte Set-Erstellung:
# Set Comprehension
quadrate = {x**2 for x in range(10)}
print(quadrate) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# Einzigartige Wortlängen aus einem Text
text = "der kleine Hund und die große Katze"
laengen = {len(wort) for wort in text.split()}
print(laengen) # {3, 5, 6}
# Alle einzigartigen Anfangsbuchstaben
anfang = {wort[0].upper() for wort in text.split()}
print(anfang) # {'D', 'K', 'H', 'U', 'G'}
Sets sind ideal fuer Mitgliedschaftstests — x in mein_set ist viel schneller als x in meine_liste, besonders bei grossen Datenmengen!