Python & AI Tutorials Logo
Python Programmierung

34. Comprehensions: Eine kompakte Methode zum Erstellen von Listen, Dictionaries und Sets

Comprehensions sind eines der elegantesten Sprachmerkmale von Python und ermöglichen es Ihnen, Sammlungen (Collections) in einer einzigen, gut lesbaren Codezeile zu erstellen und zu transformieren. Statt mehrere Zeilen mit Schleifen(loop) und append-Operationen zu schreiben, können Sie mit Comprehensions dieselbe Logik prägnanter und oft auch klarer ausdrücken.

In diesem Kapitel werden wir untersuchen, wie Sie List Comprehensions (list comprehensions), Dictionary Comprehensions (dictionary comprehensions) und Set Comprehensions (set comprehensions) verwenden, um mehr Pythonic-Code zu schreiben. Wir werden sehen, wie man bedingte Logik einbaut, wann man Comprehensions gegenüber traditionellen Schleifen bevorzugt und wie man komplexere Szenarien mit verschachtelten Iterationen behandelt.

34.1) List Comprehensions zum Erstellen und Transformieren von Listen

34.1.1) Die grundlegende Syntax einer List Comprehension

Eine List Comprehension (list comprehension) bietet eine kompakte Möglichkeit, eine neue Liste(list) zu erstellen, indem auf jedes Element einer vorhandenen Sequenz ein Ausdruck angewendet wird. Die grundlegende Syntax ist:

python
[expression for item in iterable]

Damit wird eine neue Liste erstellt, bei der jedes Element das Ergebnis der Auswertung von expression für jedes item in dem iterable ist (jede Sequenz, über die Sie iterieren können, wie eine Liste, ein Range-Objekt oder ein String).

Beginnen wir mit einem einfachen Beispiel. Angenommen, wir möchten eine Liste mit Quadratzahlen für die Zahlen 0 bis 4 erstellen:

python
# Traditioneller Ansatz mit einer Schleife
squares = []
for number in range(5):
    squares.append(number ** 2)
print(squares)  # Output: [0, 1, 4, 9, 16]

Mit einer List Comprehension können wir das prägnanter ausdrücken:

python
# Verwendung einer List Comprehension
squares = [number ** 2 for number in range(5)]
print(squares)  # Output: [0, 1, 4, 9, 16]

Beide Ansätze liefern dasselbe Ergebnis, aber die Comprehension ist kompakter und, sobald Sie mit der Syntax vertraut sind, oft leichter zu lesen. Die Comprehension zeigt klar, dass wir eine Liste aus quadrierten Werten erstellen.

34.1.2) Vorhandene Daten transformieren

List Comprehensions eignen sich hervorragend dafür, Daten von einer Form in eine andere zu transformieren. Schauen wir uns einige praktische Beispiele an.

Temperaturen von Celsius in Fahrenheit umrechnen:

python
# Temperaturdaten in Celsius
celsius_temps = [0, 10, 20, 30, 40]
 
# Umrechnung in Fahrenheit mit der Formel: F = C * 9/5 + 32
fahrenheit_temps = [temp * 9/5 + 32 for temp in celsius_temps]
print(fahrenheit_temps)  # Output: [32.0, 50.0, 68.0, 86.0, 104.0]

Strings in Großbuchstaben umwandeln:

python
# Produktcodes in gemischter Schreibweise
product_codes = ["abc123", "def456", "ghi789"]
 
# Vereinheitlichen auf Großbuchstaben
uppercase_codes = [code.upper() for code in product_codes]
print(uppercase_codes)  # Output: ['ABC123', 'DEF456', 'GHI789']

34.1.3) Listen aus Range-Objekten erstellen

List Comprehensions funktionieren natürlich mit range(), das wir in Kapitel 12 kennengelernt haben. Das ist nützlich, um Sequenzen mit bestimmten Mustern zu erzeugen:

python
# Gerade Zahlen von 0 bis 10 erzeugen
evens = [n * 2 for n in range(6)]  # n geht von 0 bis 5, also ergibt n*2: 0, 2, 4, 6, 8, 10
print(evens)  # Output: [0, 2, 4, 6, 8, 10]
 
# Vielfache von 5 erzeugen
multiples_of_five = [n * 5 for n in range(1, 6)]
print(multiples_of_five)  # Output: [5, 10, 15, 20, 25]

34.1.4) Comprehensions vs. Listenaufbau mit Append

Es ist wichtig zu verstehen, dass List Comprehensions die gesamte Liste in einem einzigen Vorgang erstellen, während der traditionelle Schleifenansatz die Liste schrittweise aufbaut. Beide liefern dasselbe Ergebnis, aber Comprehensions sind im Allgemeinen schneller beim Erstellen neuer Listen und gelten als mehr Pythonic.

Hier ist ein Vergleich nebeneinander:

python
# Traditioneller Schleifenansatz
result = []
for i in range(5):
    result.append(i * 3)
print(result)  # Output: [0, 3, 6, 9, 12]
 
# List-Comprehension-Ansatz
result = [i * 3 for i in range(5)]
print(result)  # Output: [0, 3, 6, 9, 12]

Beide Ansätze sind gültig, aber die Comprehension ist prägnanter und drückt die Absicht klar aus: „Erstellen Sie eine Liste von Werten, bei der jeder Wert i * 3 ist.“

34.2) Bedingte Logik innerhalb von List Comprehensions

34.2.1) Filtern mit if-Bedingungen

Eine der mächtigsten Eigenschaften von List Comprehensions ist die Möglichkeit, Elemente anhand einer Bedingung zu filtern. Sie können am Ende der Comprehension eine if-Klausel hinzufügen, um nur Elemente einzuschließen, die bestimmte Kriterien erfüllen:

python
[expression for item in iterable if condition]

Die if-Klausel wirkt als Filter: Python wertet die Bedingung für jedes Element aus, und nur Elemente, für die die Bedingung True ist, werden in die Ergebnisliste aufgenommen. Elemente, die die Bedingung nicht erfüllen, werden vollständig übersprungen.

Schauen wir uns das mit einem einfachen Beispiel an:

python
# Nur gerade Zahlen von 0 bis 9 holen
numbers = range(10)
evens = [n for n in numbers if n % 2 == 0]
print(evens)  # Output: [0, 2, 4, 6, 8]

Hier prüft n % 2 == 0, ob eine Zahl gerade ist. Nur Zahlen, die diesen Test bestehen, werden in die neue Liste aufgenommen.

Filtern von Schülerergebnissen:

python
# Testergebnisse von Schülern
scores = [45, 78, 92, 65, 88, 55, 73, 95]
 
# Nur bestandene Ergebnisse holen (>= 70)
passing_scores = [score for score in scores if score >= 70]
print(passing_scores)  # Output: [78, 92, 88, 73, 95]

34.2.2) Gefilterte Elemente transformieren

Sie können Filtern mit Transformation kombinieren, indem Sie auf die gefilterten Elemente einen Ausdruck anwenden:

python
# Schülerergebnisse
scores = [45, 78, 92, 65, 88, 55, 73, 95]
 
# Bestandene Ergebnisse holen und auf den Bereich 0-10 skalieren
scaled_passing = [score / 10 for score in scores if score >= 70]
print(scaled_passing)  # Output: [7.8, 9.2, 8.8, 7.3, 9.5]
# Zuerst filtern (behält nur >= 70), dann transformieren (durch 10 teilen)

Strings konvertieren und filtern:

python
# Produktnamen mit gemischter Qualität
products = ["apple", "BANANA", "cherry", "DATE", "elderberry"]
 
# Großbuchstaben-Versionen von Produkten holen, deren Namen länger als 5 Zeichen sind
long_products_upper = [product.upper() for product in products if len(product) > 5]
print(long_products_upper)  # Output: ['BANANA', 'CHERRY', 'ELDERBERRY']

34.2.3) Bedingte Ausdrücke (if-else) in Comprehensions verwenden

Manchmal möchten Sie Elemente je nach Bedingung unterschiedlich transformieren, statt sie herauszufiltern. Dafür verwenden Sie einen bedingten Ausdruck (conditional expression) (den wir in Kapitel 10 kennengelernt haben) im Ausdrucksteil der Comprehension:

python
[expression_if_true if condition else expression_if_false for item in iterable]

Das ist etwas anderes als Filtern. Hier wird jedes Element in das Ergebnis aufgenommen—das if-else bestimmt, welcher Ausdruck auf jedes Element angewendet wird. Der bedingte Ausdruck (aus Kapitel 10) steht im Ausdrucksteil, vor der for-Klausel.

Beachten Sie den Syntaxunterschied:

  • Filtern: [expr for item in seq if condition] - if am Ende, kein else
  • Bedingter Ausdruck: [expr_if if cond else expr_else for item in seq] - if-else im Ausdruck, vor for
python
# Zahlen als gerade oder ungerade klassifizieren
numbers = range(6)
classifications = ["even" if n % 2 == 0 else "odd" for n in numbers]
print(classifications)  # Output: ['even', 'odd', 'even', 'odd', 'even', 'odd']

Unterschiedliche Transformationen basierend auf Bedingungen anwenden:

python
# Schülerergebnisse
scores = [45, 78, 92, 65, 88, 55, 73, 95]
 
# Bonuspunkte zu nicht bestandenen Ergebnissen hinzufügen, bestandene Ergebnisse unverändert lassen
adjusted_scores = [score + 10 if score < 70 else score for score in scores]
print(adjusted_scores)  # Output: [55, 78, 92, 75, 88, 65, 73, 95]

In beiden Beispielen gilt:

  • Jedes Element aus der ursprünglichen Liste erscheint im Ergebnis
  • Das if-else bestimmt, zu welchem Wert jedes Element wird
  • Es wird nichts herausgefiltert

34.2.4) Den Unterschied verstehen: Filtern vs. bedingter Ausdruck

Es ist entscheidend, den Unterschied zwischen diesen beiden Mustern zu verstehen:

Filtern (if am Ende) – Einige Elemente werden ausgeschlossen:

python
# Nur positive Zahlen einschließen
numbers = [-2, 5, -1, 8, 0, 3]
positives = [n for n in numbers if n > 0]
print(positives)  # Output: [5, 8, 3]
print(len(positives))  # Output: 3 (only 3 items)
# Ablauf: Bedingung prüfen → Wenn True, Element einschließen → Wenn False, Element überspringen

Bedingter Ausdruck (if-else im Ausdruck) – Alle Elemente werden eingeschlossen, aber unterschiedlich transformiert:

python
# Negative Zahlen in null umwandeln, positive Zahlen beibehalten
numbers = [-2, 5, -1, 8, 0, 3]
non_negatives = [n if n > 0 else 0 for n in numbers]
print(non_negatives)  # Output: [0, 5, 0, 8, 0, 3]
print(len(non_negatives))  # Output: 6 (all 6 items)
# Ablauf: Bedingung prüfen → Wenn True, ersten Ausdruck verwenden → Wenn False, zweiten Ausdruck verwenden → Ergebnis immer einschließen

Am ENDE
ohne else

Im AUSDRUCK
mit else

List Comprehension
mit Bedingung

Wo steht
das if?

Filtern

Bedingter Ausdruck

[x for x in items if condition]

[x if condition else y for x in items]

Einige Elemente ausgeschlossen
Ergebnis kann kürzer sein

Alle Elemente eingeschlossen
Gleiche Länge wie das Original

34.3) Dictionary Comprehensions

34.3.1) Grundlegende Syntax einer Dictionary Comprehension

So wie List Comprehensions Listen erstellen, erstellen Dictionary Comprehensions (dictionary comprehensions) Dictionaries(dict). Die Syntax ist ähnlich, aber Sie geben sowohl einen Schlüssel als auch einen Wert an:

python
{key_expression: value_expression for item in iterable}

Damit wird ein neues Dictionary erstellt, bei dem jedes Schlüssel-Wert-Paar aus dem Iterable erzeugt wird.

Beginnen wir mit einem einfachen Beispiel, das ein Dictionary erstellt, das Zahlen auf ihre Quadrate abbildet:

python
# Ein Dictionary aus Zahlen und ihren Quadraten erstellen
squares_dict = {n: n ** 2 for n in range(5)}
print(squares_dict)  # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Ein Dictionary aus zwei Listen erstellen:

python
# Namen von Schülern und ihre Ergebnisse
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
 
# Ein Dictionary erstellen, das Namen auf Ergebnisse abbildet
student_scores = {names[i]: scores[i] for i in range(len(names))}
print(student_scores)  # Output: {'Alice': 85, 'Bob': 92, 'Charlie': 78}

Eine elegantere Möglichkeit, zwei Sequenzen zu kombinieren, ist die Verwendung von zip(), die wir in Kapitel 37 kennenlernen werden. Fürs Erste funktioniert der indexbasierte Ansatz gut.

34.3.2) Vorhandene Dictionaries transformieren

Dictionary Comprehensions eignen sich hervorragend dafür, vorhandene Dictionaries zu transformieren. Sie können Schlüssel, Werte oder beides verändern.

Wenn Sie über ein Dictionary in einer Comprehension iterieren, verwenden Sie .items(), um sowohl Schlüssel als auch Werte zu erhalten. Die Methode .items() gibt Schlüssel-Wert-Paare zurück, die Sie in der for-Klausel entpacken können:

python
# Originalpreise in Dollar
prices = {"apple": 1.50, "banana": 0.75, "cherry": 2.00}
 
# In Cent umrechnen (mit 100 multiplizieren)
prices_in_cents = {fruit: price * 100 for fruit, price in prices.items()}
print(prices_in_cents)  # Output: {'apple': 150.0, 'banana': 75.0, 'cherry': 200.0}

Schlüssel transformieren:

python
# Produktcodes in Kleinbuchstaben
codes = {"abc": 100, "def": 200, "ghi": 300}
 
# Schlüssel in Großbuchstaben umwandeln
uppercase_codes = {code.upper(): quantity for code, quantity in codes.items()}
print(uppercase_codes)  # Output: {'ABC': 100, 'DEF': 200, 'GHI': 300}

Sowohl Schlüssel als auch Werte transformieren:

python
# Namen von Schülern und Ergebnisse
scores = {"alice": 85, "bob": 92, "charlie": 78}
 
# Namen großschreiben und Ergebnisse auf den Bereich 0-10 skalieren
formatted_scores = {name.capitalize(): score / 10 for name, score in scores.items()}
print(formatted_scores)  # Output: {'Alice': 8.5, 'Bob': 9.2, 'Charlie': 7.8}

34.3.3) Dictionary-Elemente filtern

Wie bei List Comprehensions können Dictionary Comprehensions Bedingungen enthalten, um Elemente zu filtern:

python
# Schülerergebnisse
scores = {"Alice": 85, "Bob": 65, "Charlie": 92, "David": 55, "Eve": 78}
 
# Nur bestandene Ergebnisse holen (>= 70)
passing_scores = {name: score for name, score in scores.items() if score >= 70}
print(passing_scores)  # Output: {'Alice': 85, 'Charlie': 92, 'Eve': 78}

Filtern nach Eigenschaften des Schlüssels:

python
# Produktbestand
inventory = {"apple": 50, "banana": 30, "apricot": 20, "cherry": 40}
 
# Nur Produkte holen, die mit 'a' beginnen
a_products = {product: quantity for product, quantity in inventory.items() 
              if product.startswith('a')}
print(a_products)  # Output: {'apple': 50, 'apricot': 20}

34.3.4) Dictionaries aus Sequenzen erstellen

Dictionary Comprehensions sind nützlich, um Lookup-Dictionaries aus Sequenzen zu erstellen:

python
# Liste von Wörtern
words = ["python", "java", "ruby", "javascript"]
 
# Ein Dictionary erstellen, das jedes Wort auf seine Länge abbildet
word_lengths = {word: len(word) for word in words}
print(word_lengths)  # Output: {'python': 6, 'java': 4, 'ruby': 4, 'javascript': 10}

34.3.5) Bedingte Ausdrücke in Dictionary Comprehensions verwenden

Sie können bedingte Ausdrücke verwenden, um Werte je nach Bedingung unterschiedlich zu berechnen:

python
# Schülerergebnisse
scores = {"Alice": 85, "Bob": 65, "Charlie": 92, "David": 55}
 
# "Pass" oder "Fail"-Status hinzufügen
scores_with_status = {name: "Pass" if score >= 70 else "Fail" 
                      for name, score in scores.items()}
print(scores_with_status)  # Output: {'Alice': 'Pass', 'Bob': 'Fail', 'Charlie': 'Pass', 'David': 'Fail'}

Unterschiedliche Transformationen anwenden:

python
# Produktpreise
prices = {"apple": 1.50, "banana": 0.75, "cherry": 2.50}
 
# Rabatt auf teure Artikel anwenden (> $2.00)
discounted_prices = {product: price * 0.9 if price > 2.00 else price 
                     for product, price in prices.items()}
print(discounted_prices)  # Output: {'apple': 1.5, 'banana': 0.75, 'cherry': 2.25}

34.4) Set Comprehensions

34.4.1) Grundlegende Syntax einer Set Comprehension

Set Comprehensions (set comprehensions) erstellen Sets(set) mit einer Syntax, die der von List Comprehensions ähnlich ist, aber mit geschweiften Klammern:

python
{expression for item in iterable}

Das Ergebnis ist ein Set, was bedeutet, dass doppelte Werte automatisch entfernt werden und die Reihenfolge nicht garantiert ist.

python
# Ein Set aus Quadratzahlen erstellen
squares_set = {n ** 2 for n in range(6)}
print(squares_set)  # Output: {0, 1, 4, 9, 16, 25}

Der zentrale Unterschied zu List Comprehensions ist, dass Sets automatisch Duplikate eliminieren:

python
# List Comprehension – behält Duplikate
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
squared_list = [n ** 2 for n in numbers]
print(squared_list)  # Output: [1, 4, 4, 9, 9, 9, 16, 16, 16, 16]
 
# Set Comprehension – entfernt Duplikate
squared_set = {n ** 2 for n in numbers}
print(squared_set)  # Output: {16, 1, 4, 9} (Reihenfolge kann variieren)

Beachten Sie, dass die Ausgabereihenfolge des Sets von dem abweichen kann, was Sie hier sehen. Sets sind ungeordnete Collections, daher kann Python die Elemente in beliebiger Reihenfolge anzeigen.

34.4.2) Eindeutige Werte extrahieren

Set Comprehensions sind perfekt, wenn Sie eindeutige Werte aus einer Collection extrahieren müssen:

python
# Antworten von Schülern (mit Duplikaten)
responses = ["yes", "no", "yes", "maybe", "no", "yes", "maybe"]
 
# Eindeutige Antworten holen
unique_responses = {response for response in responses}
print(unique_responses)  # Output: {'maybe', 'yes', 'no'}

Eindeutige Zeichen aus Strings extrahieren:

python
# Text mit wiederholten Zeichen
text = "mississippi"
 
# Eindeutige Zeichen holen
unique_chars = {char for char in text}
print(unique_chars)  # Output: {'m', 'i', 's', 'p'}

34.4.3) Transformieren und Filtern mit Set Comprehensions

Wie andere Comprehensions können auch Set Comprehensions Transformationen und Bedingungen enthalten:

python
# Namen von Schülern
names = ["Alice", "bob", "CHARLIE", "david", "EVE"]
 
# Eindeutige Anfangsbuchstaben in Großbuchstaben holen
first_letters = {name[0].upper() for name in names}
print(first_letters)  # Output: {'A', 'B', 'C', 'D', 'E'}

Filtern mit Bedingungen:

python
# Zahlen mit Duplikaten
numbers = [1, -2, 3, -4, 5, -2, 3, 6, -4]
 
# Eindeutige positive Zahlen holen
positive_numbers = {n for n in numbers if n > 0}
print(positive_numbers)  # Output: {1, 3, 5, 6}

34.4.4) Wann Set Comprehensions am nützlichsten sind

Set Comprehensions sind besonders wertvoll, wenn:

  1. Sie eindeutige Werte benötigen: Duplikate werden automatisch entfernt
  2. Die Reihenfolge keine Rolle spielt: Sets sind ungeordnet, verwenden Sie sie also, wenn die Reihenfolge nicht wichtig ist
  3. Sie Mengenoperationen durchführen werden: Das Ergebnis kann mit Vereinigung, Schnittmenge usw. verwendet werden (wie wir in Kapitel 17 gelernt haben)
python
# Kursbelegungen von Schülern in zwei Kursen
course_a = ["Alice", "Bob", "Charlie", "David"]
course_b = ["Charlie", "David", "Eve", "Frank"]
 
# Eindeutige Schüler über beide Kurse hinweg mit Set Comprehension holen
all_students = {student for course in [course_a, course_b] for student in course}
print(all_students)  # Output: {'Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'}

34.5) Comprehensions vs. Schleifen auswählen

34.5.1) Wann Comprehensions besser sind

Comprehensions werden im Allgemeinen bevorzugt, wenn Sie eine neue Collection erstellen, indem Sie eine vorhandene transformieren oder filtern. Sie sind prägnanter, oft besser lesbar und typischerweise schneller als gleichwertige Schleifen.

Comprehensions sind besonders gut geeignet, wenn:

  1. Sie eine neue Collection aus einer vorhandenen erstellen:
python
# Guter Einsatz einer Comprehension
prices = [10.99, 25.50, 8.75, 15.00]
discounted = [price * 0.9 for price in prices]
  1. Die Transformation unkompliziert ist:
python
# Klar und prägnant
names = ["alice", "bob", "charlie"]
uppercase_names = [name.upper() for name in names]
  1. Sie anhand einfacher Bedingungen filtern:
python
# Leicht zu verstehen
scores = [85, 92, 78, 65, 88, 55, 73, 95]
passing = [score for score in scores if score >= 70]

34.5.2) Wann traditionelle Schleifen besser sind

Es gibt jedoch Situationen, in denen traditionelle Schleifen geeigneter und besser lesbar sind:

Verwenden Sie Schleifen, wenn:

  1. Die Logik komplex ist oder mehrere Schritte umfasst:
python
# Zu komplex für eine Comprehension
results = []
for score in scores:
    if score >= 90:
        grade = "A"
    elif score >= 80:
        grade = "B"
    elif score >= 70:
        grade = "C"
    else:
        grade = "F"
    results.append({"score": score, "grade": grade})

Obwohl Sie das könnten als Comprehension schreiben, wäre es viel schwieriger zu lesen.

  1. Sie Aktionen ausführen müssen, die über das Erstellen von Collections hinausgehen:
python
# Eine Schleife ist klarer, wenn I/O oder Side Effects ausgeführt werden
for filename in files:
    with open(filename) as f:
        content = f.read()
        print(f"Processing {filename}")
        # ... weitere Verarbeitung
  1. Sie eine vorhandene Collection in place ändern müssen:
python
# Eine Liste in place ändern – dafür kann man keine Comprehension verwenden
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers)):
    numbers[i] *= 2
print(numbers)  # Output: [2, 4, 6, 8, 10]
  1. Sie break oder continue mit komplexer Logik verwenden müssen:
python
# Erstes Auftreten finden mit zusätzlicher Verarbeitung
found = None
for item in items:
    if item.startswith("target"):
        found = item
        print(f"Found: {found}")
        break

34.5.3) Überlegungen zur Lesbarkeit

Der wichtigste Faktor ist die Lesbarkeit. Wenn eine Comprehension zu lang oder zu komplex wird, zerlegen Sie sie in eine traditionelle Schleife:

python
# Schwer zu lesen – in einer Zeile passiert zu viel
result = [item.upper().strip() for item in items if len(item) > 5 and item.startswith('a')]
 
# Besser – eine Schleife verwenden, wenn die Logik komplex ist
result = []
for item in items:
    if len(item) > 5 and item.startswith('a'):
        cleaned = item.strip().upper()
        result.append(cleaned)

Eine gute Faustregel: Wenn Ihre Comprehension nicht bequem in eine Zeile passt (oder höchstens in zwei Zeilen mit klarer Formatierung), sollten Sie stattdessen eine Schleife verwenden.

34.5.4) Performance-Überlegungen

Comprehensions sind im Allgemeinen schneller als gleichwertige Schleifen, weil sie auf Interpreter-Ebene optimiert sind. Dieser Performance-Unterschied ist jedoch für kleine bis mittelgroße Collections meist vernachlässigbar.

python
# Beide liefern dasselbe Ergebnis
# Comprehension ist etwas schneller
squares_comp = [n ** 2 for n in range(1000)]
 
# Schleife ist etwas langsamer, aber flexibler
squares_loop = []
for n in range(1000):
    squares_loop.append(n ** 2)

Für die meisten praktischen Zwecke sollten Sie nach Lesbarkeit statt nach Performance entscheiden. Optimieren Sie nur dann auf Geschwindigkeit, wenn Profiling zeigt, dass eine bestimmte Operation ein Bottleneck ist.

34.5.5) Ansätze kombinieren

Manchmal kombiniert die beste Lösung beide Ansätze:

python
# Comprehension für einfache Transformation verwenden
student_data = [
    {"name": "Alice", "score": 85},
    {"name": "Bob", "score": 92},
    {"name": "Charlie", "score": 78}
]
 
# Ergebnisse mit Comprehension extrahieren
scores = [student["score"] for student in student_data]
 
# Schleife für komplexe Verarbeitung verwenden
for student in student_data:
    score = student["score"]
    if score >= 90:
        print(f"{student['name']}: Excellent!")
    elif score >= 80:
        print(f"{student['name']}: Good job!")
    else:
        print(f"{student['name']}: Keep working!")

Ja

Nein

Ja

Nein

Ja

Nein

Ja

Nein

Müssen Sie eine Collection erstellen?

Einfache Transformation
oder Filterung?

Comprehension verwenden

Komplexe Logik oder
mehrere Schritte?

Schleife verwenden

Side Effects
oder I/O nötig?

Passt in 1-2 Zeilen
und ist lesbar?

34.6) Verschachtelte Schleifen und mehrere for-Klauseln

34.6.1) Mehrere for-Klauseln verstehen

Comprehensions können mehrere for-Klauseln enthalten, was verschachtelten Schleifen entspricht. Die Syntax ist:

python
[expression for item1 in iterable1 for item2 in iterable2]

Das ist äquivalent zu:

python
result = []
for item1 in iterable1:
    for item2 in iterable2:
        result.append(expression)

Der entscheidende Punkt ist, dass die for-Klauseln von links nach rechts gelesen werden, genauso wie verschachtelte Schleifen von oben nach unten geschrieben werden.

Beginnen wir mit einem einfachen Beispiel, das alle Kombinationen aus zwei Listen erstellt:

python
# Zwei Listen mit Werten
colors = ["red", "blue"]
sizes = ["S", "M", "L"]
 
# Alle Kombinationen erstellen
combinations = [(color, size) for color in colors for size in sizes]
print(combinations)
# Output: [('red', 'S'), ('red', 'M'), ('red', 'L'), ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]

Damit wird jede mögliche Paarung einer Farbe mit einer Größe erstellt.

34.6.2) Koordinatenpaare erstellen

Ein häufiger Anwendungsfall ist das Generieren von Koordinatenpaaren:

python
# Ein 3x3-Koordinatengitter erstellen
coordinates = [(x, y) for x in range(3) for y in range(3)]
print(coordinates)
# Output: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Eine Multiplikationstabelle erstellen:

python
# Multiplikations-Tupel erzeugen
products = [(x, y, x * y) for x in range(1, 4) for y in range(1, 4)]
for x, y, product in products:
    print(f"{x} × {y} = {product}")
# Output:
# 1 × 1 = 1
# 1 × 2 = 2
# 1 × 3 = 3
# 2 × 1 = 2
# 2 × 2 = 4
# 2 × 3 = 6
# 3 × 1 = 3
# 3 × 2 = 6
# 3 × 3 = 9

34.6.3) Verschachtelte Listen flatten

Mehrere for-Klauseln sind nützlich, um verschachtelte Strukturen zu flatten:

python
# Verschachtelte Liste mit Zahlen
nested_numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
# In eine einzelne Liste flatten
flat = [num for sublist in nested_numbers for num in sublist]
print(flat)  # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Das ist äquivalent zu:

python
flat = []
for sublist in nested_numbers:
    for num in sublist:
        flat.append(num)

Eine Wortliste in Zeichen flatten:

python
# Liste von Wörtern
words = ["cat", "dog", "bird"]
 
# Alle Zeichen aus allen Wörtern holen
all_chars = [char for word in words for char in word]
print(all_chars)  # Output: ['c', 'a', 't', 'd', 'o', 'g', 'b', 'i', 'r', 'd']

34.6.4) Bedingungen zu verschachtelten Comprehensions hinzufügen

Sie können Bedingungen hinzufügen, um die Ergebnisse zu filtern:

python
# Paare erstellen, bei denen die Summe gerade ist
pairs = [(x, y) for x in range(5) for y in range(5) if (x + y) % 2 == 0]
print(pairs)
# Output: [(0, 0), (0, 2), (0, 4), (1, 1), (1, 3), (2, 0), (2, 2), (2, 4), (3, 1), (3, 3), (4, 0), (4, 2), (4, 4)]

Gemeinsame Elemente zwischen Listen finden:

python
# Zwei Listen mit Zahlen
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
 
# Paare finden, bei denen die Werte gleich sind (gemeinsame Elemente)
common = [x for x in list1 for y in list2 if x == y]
print(common)  # Output: [4, 5]

Hinweis: Um gemeinsame Elemente zu finden, ist die Verwendung der Schnittmenge von Sets effizienter: set(list1) & set(list2), was wir in Kapitel 17 gelernt haben.

34.6.5) Verschachtelte Dictionary Comprehensions

Sie können auch mehrere for-Klauseln in Dictionary Comprehensions verwenden:

python
# Ein Dictionary aus Koordinatensummen erstellen
coord_sums = {(x, y): x + y for x in range(3) for y in range(3)}
print(coord_sums)
# Output: {(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 0): 1, (1, 1): 2, (1, 2): 3, (2, 0): 2, (2, 1): 3, (2, 2): 4}

34.6.6) Wann man verschachtelte Comprehensions vermeiden sollte

Während verschachtelte Comprehensions mächtig sind, können sie schnell schwer zu lesen werden. Beachten Sie diese Richtlinien:

Akzeptabel – relativ einfach:

python
# Zwei Verschachtelungsebenen, einfacher Ausdruck
matrix = [[i * j for j in range(3)] for i in range(3)]
print(matrix)  # Output: [[0, 0, 0], [0, 1, 2], [0, 2, 4]]

Wird komplex – erwägen Sie eine Schleife:

python
# Drei Verschachtelungsebenen – schwer zu lesen
result = [[[i + j + k for k in range(2)] for j in range(2)] for i in range(2)]
# Besser mit verschachtelten Schleifen für Klarheit

Faustregel: Wenn Sie mehr als zwei for-Klauseln haben oder wenn der Ausdruck komplex ist, verwenden Sie stattdessen traditionelle verschachtelte Schleifen:

python
# Klarer mit expliziten Schleifen
result = []
for i in range(2):
    middle = []
    for j in range(2):
        inner = []
        for k in range(2):
            inner.append(i + j + k)
        middle.append(inner)
    result.append(middle)

Comprehensions mit mehreren for-Klauseln sind mächtige Werkzeuge, aber denken Sie daran: Klarheit ist wichtiger als Kürze. Wenn eine verschachtelte Comprehension schwer zu verstehen wird, ist es besser, explizite Schleifen zu verwenden.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai