List Comprehensions in Python
Lerne List Comprehensions, Dictionary Comprehensions und Generator Expressions -- die elegante Art, Daten in Python zu transformieren.
Was sind List Comprehensions?
List Comprehensions sind eine kompakte Schreibweise, um neue Listen aus bestehenden Daten zu erstellen. Sie sind eines der beliebtesten Features von Python.
Statt:
# Klassisch mit for-Schleife
quadrate = []
for x in range(10):
quadrate.append(x ** 2)
print(quadrate) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Schreibst du einfach:
# Mit List Comprehension
quadrate = [x ** 2 for x in range(10)]
print(quadrate) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Das Ergebnis ist identisch, aber der Code ist kuerzer, lesbarer und schneller.
Grundsyntax
Die Grundform einer List Comprehension:
[ausdruck for variable in iterable]
- ausdruck: Was in die neue Liste kommt (Transformation).
- variable: Der Name fuer jedes Element.
- iterable: Die Quelle der Daten.
Einfache Beispiele
# Zahlen verdoppeln
verdoppelt = [x * 2 for x in range(6)]
print(verdoppelt) # [0, 2, 4, 6, 8, 10]
# Strings in Grossbuchstaben umwandeln
namen = ["anna", "bob", "clara"]
gross = [name.upper() for name in namen]
print(gross) # ['ANNA', 'BOB', 'CLARA']
# Laenge jedes Strings berechnen
woerter = ["Hallo", "Welt", "Python", "Programmierung"]
laengen = [len(wort) for wort in woerter]
print(laengen) # [5, 4, 6, 15]
# Temperatur von Celsius zu Fahrenheit
celsius = [0, 10, 20, 30, 40]
fahrenheit = [(c * 9/5) + 32 for c in celsius]
print(fahrenheit) # [32.0, 50.0, 68.0, 86.0, 104.0]
Mit Bedingung: Filtern
Du kannst eine if-Bedingung hinzufuegen, um Elemente zu filtern:
[ausdruck for variable in iterable if bedingung]
Beispiele
# Nur gerade Zahlen
gerade = [x for x in range(20) if x % 2 == 0]
print(gerade) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Nur positive Zahlen
zahlen = [5, -3, 8, -1, 0, 7, -4]
positiv = [x for x in zahlen if x > 0]
print(positiv) # [5, 8, 7]
# Nur Woerter mit mehr als 4 Buchstaben
woerter = ["Hi", "Hallo", "Welt", "Python", "OK"]
lang = [w for w in woerter if len(w) > 4]
print(lang) # ['Hallo', 'Python']
# Nur Zahlen aus einem gemischten Text extrahieren
zeichen = "a1b2c3d4e5"
ziffern = [z for z in zeichen if z.isdigit()]
print(ziffern) # ['1', '2', '3', '4', '5']
Mit if-else im Ausdruck
Beachte den Unterschied: if zum Filtern steht am Ende, if-else zur Transformation steht im Ausdruck:
# if zum Filtern (am Ende):
gerade = [x for x in range(10) if x % 2 == 0]
print(gerade) # [0, 2, 4, 6, 8]
# if-else zur Transformation (im Ausdruck):
labels = ["gerade" if x % 2 == 0 else "ungerade" for x in range(6)]
print(labels) # ['gerade', 'ungerade', 'gerade', 'ungerade', 'gerade', 'ungerade']
# Negative Zahlen durch 0 ersetzen
zahlen = [5, -3, 8, -1, 0, 7]
bereinigt = [x if x >= 0 else 0 for x in zahlen]
print(bereinigt) # [5, 0, 8, 0, 0, 7]
# Absolute Werte berechnen (ohne abs())
absolut = [x if x >= 0 else -x for x in zahlen]
print(absolut) # [5, 3, 8, 1, 0, 7]
Vergleich: for-Schleife vs Comprehension
Hier siehst du den Unterschied in der Lesbarkeit:
Beispiel 1: Quadratzahlen
# for-Schleife (4 Zeilen)
quadrate = []
for x in range(10):
quadrate.append(x ** 2)
# Comprehension (1 Zeile)
quadrate = [x ** 2 for x in range(10)]
Beispiel 2: Filtern und Transformieren
# for-Schleife (5 Zeilen)
ergebnis = []
for name in namen:
if len(name) > 3:
ergebnis.append(name.upper())
# Comprehension (1 Zeile)
ergebnis = [name.upper() for name in namen if len(name) > 3]
Beispiel 3: Verschachtelte Logik
noten = [1.3, 2.7, 4.5, 1.0, 3.3, 5.0, 2.0]
# for-Schleife
bestanden = []
for note in noten:
if note <= 4.0:
bestanden.append(note)
# Comprehension
bestanden = [note for note in noten if note <= 4.0]
print(bestanden) # [1.3, 2.7, 1.0, 3.3, 2.0]
Verschachtelte Comprehensions
Du kannst auch verschachtelte Schleifen in einer Comprehension ausdruecken:
# Alle Kombinationen
farben = ["rot", "gruen"]
groessen = ["S", "M", "L"]
# for-Schleife
kombinationen = []
for farbe in farben:
for groesse in groessen:
kombinationen.append(f"{farbe}-{groesse}")
# Comprehension
kombinationen = [f"{farbe}-{groesse}" for farbe in farben for groesse in groessen]
print(kombinationen)
# ['rot-S', 'rot-M', 'rot-L', 'gruen-S', 'gruen-M', 'gruen-L']
Die Reihenfolge in der Comprehension entspricht der Reihenfolge der verschachtelten Schleifen: Die aeussere Schleife kommt zuerst.
Matrix erstellen
# 3x3 Matrix mit Nullen
matrix = [[0 for spalte in range(3)] for zeile in range(3)]
print(matrix) # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# Identitaetsmatrix
identitaet = [[1 if i == j else 0 for j in range(3)] for i in range(3)]
for zeile in identitaet:
print(zeile)
# [1, 0, 0]
# [0, 1, 0]
# [0, 0, 1]
Matrix flach machen (flatten)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Verschachtelte Schleife
flach = []
for zeile in matrix:
for element in zeile:
flach.append(element)
# Comprehension
flach = [element for zeile in matrix for element in zeile]
print(flach) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Dictionary Comprehensions
Genau wie Listen kannst du auch Dictionaries mit Comprehensions erstellen:
{schluessel: wert for variable in iterable}
Beispiele
# Quadratzahlen als Dictionary
quadrate = {x: x ** 2 for x in range(6)}
print(quadrate) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Woerter und ihre Laengen
woerter = ["Python", "Java", "C", "JavaScript"]
laengen = {wort: len(wort) for wort in woerter}
print(laengen) # {'Python': 6, 'Java': 4, 'C': 1, 'JavaScript': 10}
# Celsius zu Fahrenheit
celsius_werte = [0, 10, 20, 30, 40]
temp_dict = {c: round((c * 9/5) + 32, 1) for c in celsius_werte}
print(temp_dict) # {0: 32.0, 10: 50.0, 20: 68.0, 30: 86.0, 40: 104.0}
Filtern in Dictionary Comprehensions
noten = {"Anna": 1.3, "Bob": 4.7, "Clara": 2.0, "David": 5.0, "Eva": 1.7}
# Nur bestandene Studierende
bestanden = {name: note for name, note in noten.items() if note <= 4.0}
print(bestanden) # {'Anna': 1.3, 'Clara': 2.0, 'Eva': 1.7}
# Schluessel und Werte tauschen
getauscht = {note: name for name, note in noten.items()}
print(getauscht) # {1.3: 'Anna', 4.7: 'Bob', 2.0: 'Clara', 5.0: 'David', 1.7: 'Eva'}
Dictionary aus zwei Listen erstellen
schluessel = ["name", "alter", "stadt"]
werte = ["Anna", 25, "Berlin"]
person = {s: w for s, w in zip(schluessel, werte)}
print(person) # {'name': 'Anna', 'alter': 25, 'stadt': 'Berlin'}
# Noch einfacher mit dict():
person = dict(zip(schluessel, werte))
print(person) # {'name': 'Anna', 'alter': 25, 'stadt': 'Berlin'}
Set Comprehensions
Sets (Mengen) haben keine Duplikate. Set Comprehensions verwenden geschweifte Klammern:
{ausdruck for variable in iterable}
Beispiele
# Eindeutige Quadratzahlen
zahlen = [1, 2, 2, 3, 3, 3, 4]
quadrate = {x ** 2 for x in zahlen}
print(quadrate) # {16, 1, 4, 9} -- keine Duplikate, ungeordnet
# Alle Vokale in einem Text
text = "Programmieren lernen macht Spass"
vokale = {z.lower() for z in text if z.lower() in "aeiou"}
print(vokale) # {'a', 'e', 'i', 'o'}
# Eindeutige Wortlaengen
saetze = ["Hallo Welt", "Python ist toll", "Programmieren macht Spass"]
wort_laengen = {len(wort) for satz in saetze for wort in satz.split()}
print(wort_laengen) # {3, 4, 5, 14, ...}
Generator Expressions — Kurze Einfuehrung
Generator Expressions sehen aus wie List Comprehensions, verwenden aber runde Klammern statt eckiger:
# List Comprehension -- erstellt sofort die gesamte Liste im Speicher
quadrate_liste = [x ** 2 for x in range(1000000)]
# Generator Expression -- berechnet Werte erst bei Bedarf
quadrate_gen = (x ** 2 for x in range(1000000))
Der Unterschied
# Liste: Alle Werte sofort im Speicher
liste = [x ** 2 for x in range(5)]
print(liste) # [0, 1, 4, 9, 16]
print(type(liste)) # <class 'list'>
# Generator: Werte werden "on-the-fly" berechnet
gen = (x ** 2 for x in range(5))
print(gen) # <generator object ...>
print(type(gen)) # <class 'generator'>
# Generator-Werte abrufen
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 4
# Oder in einer Schleife
for wert in gen:
print(wert) # 9, 16 (die restlichen Werte)
Wann Generator statt Liste?
# Perfekt fuer sum(), min(), max() -- kein Klammer-Doppel noetig!
summe = sum(x ** 2 for x in range(1000000))
print(summe)
maximum = max(len(wort) for wort in ["Hallo", "Welt", "Python"])
print(maximum) # 6
# Pruefen, ob eine Bedingung fuer mindestens ein Element gilt
zahlen = [2, 4, 6, 7, 8]
hat_ungerade = any(x % 2 != 0 for x in zahlen)
print(hat_ungerade) # True
# Pruefen, ob eine Bedingung fuer ALLE Elemente gilt
alle_positiv = all(x > 0 for x in zahlen)
print(alle_positiv) # True
Generator Expressions sind speichereffizient — sie halten nicht alle Werte gleichzeitig im Speicher. Ideal fuer grosse Datenmengen.
Wann Comprehensions, wann normale Schleifen?
Verwende Comprehensions, wenn:
- Du eine neue Liste/Dict/Set aus bestehenden Daten erstellst.
- Die Logik in eine Zeile passt und lesbar bleibt.
- Du Elemente transformieren oder filtern willst.
# Perfekt fuer Comprehensions:
quadrate = [x ** 2 for x in range(10)]
positiv = [x for x in zahlen if x > 0]
namen_dict = {name: len(name) for name in namen}
Verwende normale Schleifen, wenn:
- Du Seiteneffekte hast (print, Datei schreiben, etc.).
- Die Logik komplex ist (mehrere Bedingungen, verschachtelte Logik).
- Du kein neues Objekt erstellst, sondern etwas anderes tust.
- Die Comprehension schwer lesbar waere.
# Besser als normale Schleife:
for datei in dateien:
verarbeite(datei)
speichere_ergebnis(datei)
# NICHT als Comprehension! (Seiteneffekte, kein Rueckgabewert)
# [verarbeite(datei) for datei in dateien] # Anti-Pattern!
Performance-Vorteile
List Comprehensions sind in der Regel schneller als aequivalente for-Schleifen:
import time
n = 1_000_000
# for-Schleife
start = time.time()
ergebnis1 = []
for x in range(n):
ergebnis1.append(x ** 2)
zeit_for = time.time() - start
# Comprehension
start = time.time()
ergebnis2 = [x ** 2 for x in range(n)]
zeit_comp = time.time() - start
print(f"for-Schleife: {zeit_for:.4f}s")
print(f"Comprehension: {zeit_comp:.4f}s")
print(f"Speedup: {zeit_for / zeit_comp:.1f}x")
Typisches Ergebnis: Comprehensions sind 20-30% schneller, weil Python sie intern optimiert (der append()-Aufruf entfaellt).
Lesbarkeit: Nicht uebertreiben!
Comprehensions sind maechtig, aber Lesbarkeit geht vor:
Gut lesbar
# Einfache Transformation
preise_netto = [100, 200, 350, 500]
preise_brutto = [preis * 1.19 for preis in preise_netto]
# Einfacher Filter
erwachsene = [p for p in personen if p["alter"] >= 18]
Noch OK
# Transformation + Filter
rabatt_preise = [preis * 0.9 for preis in preise if preis > 100]
Zu komplex — lieber eine normale Schleife
# SCHLECHT: Zu verschachtelt und schwer lesbar
ergebnis = [
f"{v}-{n}" for v in vornamen for n in nachnamen
if len(v) > 3 and n[0] == v[0] and (v, n) not in ausnahmen
]
# BESSER: Normale Schleife mit klarer Struktur
ergebnis = []
for v in vornamen:
for n in nachnamen:
if len(v) > 3 and n[0] == v[0]:
if (v, n) not in ausnahmen:
ergebnis.append(f"{v}-{n}")
Faustregel
Wenn du die Comprehension nicht in 5 Sekunden verstehst, schreib eine normale Schleife.
Praxis-Beispiele
Textverarbeitung
# Saetze bereinigen und filtern
rohdaten = [" Hallo Welt ", "", " Python ", " ", " Code "]
bereinigt = [s.strip() for s in rohdaten if s.strip()]
print(bereinigt) # ['Hallo Welt', 'Python', 'Code']
# Woerter zaehlen
text = "Python ist toll und Python ist einfach"
wort_haeufigkeit = {}
for wort in text.lower().split():
wort_haeufigkeit[wort] = wort_haeufigkeit.get(wort, 0) + 1
# Oder als Comprehension (mit Counter):
from collections import Counter
wort_haeufigkeit = Counter(text.lower().split())
print(dict(wort_haeufigkeit))
Daten transformieren
# CSV-Daten verarbeiten
csv_zeilen = [
"Anna,25,Berlin",
"Bob,30,Hamburg",
"Clara,22,Muenchen"
]
personen = [
{"name": z.split(",")[0], "alter": int(z.split(",")[1]), "stadt": z.split(",")[2]}
for z in csv_zeilen
]
print(personen)
# Nur Personen ueber 24
aeltere = [p for p in personen if p["alter"] > 24]
print(aeltere)
Mathematische Operationen
# Fibonacci-aehnlich: Quadratzahlen, die durch 3 teilbar sind
ergebnis = [x ** 2 for x in range(1, 21) if (x ** 2) % 3 == 0]
print(ergebnis) # [9, 36, 81, 144, 225, 324]
# Pythagoraeische Tripel bis 20
tripel = [
(a, b, c)
for a in range(1, 21)
for b in range(a, 21)
for c in range(b, 21)
if a ** 2 + b ** 2 == c ** 2
]
print(tripel)
# [(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]
Verschluesseln / Entschluesseln
# Einfache Caesar-Verschluesselung
def caesar(text, verschiebung):
return "".join(
chr((ord(z) - ord('a') + verschiebung) % 26 + ord('a'))
if z.isalpha() and z.islower()
else z
for z in text
)
verschluesselt = caesar("hallo welt", 3)
print(verschluesselt) # "kdoor zhow"
entschluesselt = caesar(verschluesselt, -3)
print(entschluesselt) # "hallo welt"
Uebungen
Uebung 1: Gerade Quadrate
Erstelle mit einer List Comprehension eine Liste aller Quadratzahlen von 1 bis 20, die gerade sind.
Loesung anzeigen
gerade_quadrate = [x ** 2 for x in range(1, 21) if (x ** 2) % 2 == 0]
print(gerade_quadrate) # [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]
Uebung 2: Initialen
Erstelle aus einer Liste von vollen Namen eine Liste der Initialen.
namen = ["Max Mustermann", "Anna Schmidt", "Bob Mueller"]
# Erwartet: ["MM", "AS", "BM"]
Loesung anzeigen
namen = ["Max Mustermann", "Anna Schmidt", "Bob Mueller"]
initialen = ["".join(teil[0] for teil in name.split()) for name in namen]
print(initialen) # ['MM', 'AS', 'BM']
Uebung 3: Wort-Laengen-Dictionary
Erstelle ein Dictionary, das Woerter auf ihre Laenge abbildet. Filtere Woerter mit weniger als 4 Buchstaben heraus.
satz = "Python ist eine großartige Programmiersprache fuer Anfaenger"
# Erwartet: {'Python': 6, 'eine': 4, ...}
Loesung anzeigen
satz = "Python ist eine grossartige Programmiersprache fuer Anfaenger"
wort_laengen = {wort: len(wort) for wort in satz.split() if len(wort) >= 4}
print(wort_laengen)
# {'Python': 6, 'eine': 4, 'grossartige': 11, 'Programmiersprache': 18, 'fuer': 4, 'Anfaenger': 9}
Uebung 4: Matrix-Transposition
Transponiere eine Matrix (Zeilen und Spalten tauschen) mit einer verschachtelten List Comprehension.
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Erwartet: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Loesung anzeigen
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
transponiert = [[zeile[i] for zeile in matrix] for i in range(len(matrix[0]))]
for zeile in transponiert:
print(zeile)
# [1, 4, 7]
# [2, 5, 8]
# [3, 6, 9]
Uebung 5: Verschachtelt zu Flach
Erstelle eine Comprehension, die eine verschachtelte Liste von Zahlen flach macht und nur die geraden Zahlen behaelt.
verschachtelt = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
# Erwartet: [2, 4, 6, 8, 10, 12]
Loesung anzeigen
verschachtelt = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
flach_gerade = [x for gruppe in verschachtelt for x in gruppe if x % 2 == 0]
print(flach_gerade) # [2, 4, 6, 8, 10, 12]
Pro-Tipp: Comprehensions debuggen
Wenn eine Comprehension nicht das tut, was du erwartest, wandle sie zurueck in eine for-Schleife und fuge print()-Aufrufe ein:
# Diese Comprehension liefert unerwartete Ergebnisse?
ergebnis = [x ** 2 for x in range(10) if x % 3 == 0]
# Zum Debuggen aufloesen:
ergebnis = []
for x in range(10):
print(f"x={x}, x%3={x%3}, x**2={x**2}")
if x % 3 == 0:
ergebnis.append(x ** 2)
print(f" -> Hinzugefuegt: {x**2}")
print(ergebnis)
Wenn du die Schleife verstanden und den Fehler behoben hast, kannst du sie wieder zur Comprehension zusammenfassen.