# Python: For-Loop verstehen und anwenden

Die For-Loop in Python, zu Deutsch „For-Schleife“, dient zum **wiederholten Ausführen eines Code-Blocks**. For-Schleifen sind grundlegender Bestandteil der meisten Programmiersprachen. Wir zeigen, wie die For-Loop in Python funktioniert und wie sie eingesetzt wird.

## Was ist die For-Schleife in Python?

Die For-Schleife ist neben der if-else-Verzweigung das wohl bekannteste Programmierkonstrukt. Generationen von Studierenden haben sich am informatischen Konzept der Schleife das Hirn zermartert. Denn **Schleifen sind zunächst wenig intuitiv**. Dabei entstehen die Verständnisprobleme möglicherweise mehr durch die Art, wie die Materie präsentiert wird. Denn an sich sind Schleifen nichts Außergewöhnliches.

Verdeutlichen wir uns das Konzept der Schleife an einem anschaulichen Beispiel. Stellen wir uns eine Schulklasse vor. Die **Lehrkraft möchte im Rahmen eines Experiments die durchschnittliche Größe der Kinder ermitteln**. Dazu fragt sie nach und nach jedes Kind nach dessen Größe und addiert die einzelnen Größen zu einer laufenden Summe. Im Anschluss teilt sie die Summe durch die Anzahl der Kinder, um die durchschnittliche Größe zu erhalten. Wir abstrahieren einen simplen Algorithmus aus dem Vorgehen der Lehrkraft:

1. Größe jedes Kindes abfragen und zu laufender Summe addieren
2. Summe durch Anzahl der Kinder teilen

Der erste Schritt wird für jedes Kind einmal ausgeführt und ist damit **abhängig von der zahlenmäßigen Größe der Klasse**. Der zweite Schritt wird unabhängig von der Größe der Klasse nur einmal ausgeführt. Eine Schleife benötigen wir für den ersten Schritt. Hier ein Code-Beispiel, das die Durchschnittsgröße eines Schulkinds mit einer For-Schleife in Python berechnet:

```none
children_heights = [155, 171, 148, 161, 158, 153, 162]
height_sum = 0
for height in children_heights:
    height_sum = height_sum + height
average_height = height_sum // len(children_heights)
print(average_height)
```

Die For-Schleife in Python führt einen Code-Block wiederholt aus. Man spricht dabei auch von „Iteration“. Insbesondere erlauben Schleifen, mehrere in einer „Kollektion“ zusammengefasste **Elemente einzeln nach demselben Schema zu verarbeiten**. Eine For-Schleife nutzen wir dann, wenn sich der Umfang der Kollektion zur Laufzeit des Programms feststellen lässt. Ist dies nicht der Fall, kommt für gewöhnlich eine [While-Schleife](https://www.ionos.de/digitalguide/websites/web-entwicklung/python-while-loop/ "Python While-Loop") zum Einsatz.

---

### Tipp

Lernen Sie, selbstständig Python-Code zu schreiben – mit unserem [Python-Tutorial](https://www.ionos.de/digitalguide/websites/web-entwicklung/python-tutorial/ "Python-Tutorial")!

---

## Was unterscheidet die For-Schleife in Python von anderen Sprachen?

Viele Programmiersprachen kennen das Konzept der For-Schleife. Neben Python ist diese auch in anderen Sprachen wie C, Java, JavaScript und PHP ein **grundlegendes Konstrukt**. Rein funktionale Sprachen wie Haskell oder Lisp kommen für gewöhnlich ohne explizite For-Schleife aus. Anstelle von Iteration werden in diesen Sprachen rekursive Funktionen eingesetzt.

Alle Schleifen haben gemeinsam, dass ein Code-Block wiederholt ausgeführt wird. Jedoch **unterscheidet sich der Wirkmechanismus der For-Schleife in Python deutlich** von anderen Sprachen. So kommt bei den meisten Programmiersprachen eine sogenannte Schleifen-Variable zum Einsatz, die beim Durchlaufen der Schleife hochgezählt (inkrementiert) bzw. runtergezählt (dekrementiert) wird.

<table>
  <thead>
    <tr>
      <th>Operation</th>
      <th>Bedeutung</th>
      <th>Herkömmliche Syntax</th>
      <th>Python-Syntax</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Inkrementieren</td>
      <td>Wert einer Ganzzahl-Variable um bestimmten, festen Betrag erhöhen</td>
      <td>i++</td>
      <td>index += 1</td>
    </tr>
    <tr>
      <td>Dekrementieren</td>
      <td>Wert einer Ganzzahl-Variable um bestimmten, festen Betrag verringern</td>
      <td>i--</td>
      <td>index -= 1</td>
    </tr>
  </tbody>
</table>

Betrachten wir an einem Beispiel, wie eine For-Schleife in anderen Sprachen funktioniert. Wir **geben die Zahlen von 0 bis 9 in JavaScript mit einer For-Schleife aus**. Wir definieren eine Ganzzahl-Variable 'number' und inkrementieren diese, solange die enthaltene Zahl kleiner als 10 ist. Der dabei zum Einsatz kommende Code wirkt auf Neulinge eher kryptisch:

```none
for ( let number = 0; number < 10; number++ ) {
    console.log(number);
}
```

Der Code für eine **korrespondierende For-Schleife in Python** wirkt deutlich aufgeräumter:

```none
for number in range(10):
    print(number)
```

Anstatt den Wert der Schleifen-Variable direkt auszugeben, wird dieser in der Praxis meist zum **Indizieren eines Elements innerhalb einer Kollektion** genutzt. Wiederum zunächst ein Beispiel in JavaScript: Wir geben die in der Liste 'people' enthaltenen Namen nacheinander aus. Dabei nutzen wir die Schleifen-Variable 'i' als fortlaufenden Index der einzelnen Elemente:

```none
people = ['Jack', 'Jim', 'John']
for (let i = 0; i < people.length; i++) {
    console.log("Here comes " + people[i]);
}
```

Das direkte Indizieren sukzessiver Listen-Elemente ist mit Vorsicht zu genießen. Denn ein versuchter Zugriff außerhalb erlaubter Grenzen führt zu einem Laufzeitfehler. In der Regel handelt es sich dabei um den berüchtigten „Off-by-one Error“. Python macht vor, dass es auch anders geht. Hier dasselbe Beispiel mit einer For-Loop in Python – wir **iterieren direkt über den Listen-Elementen**, ohne diese mit einer Schleifen-Variable zu indizieren:

```none
people = ['Jack', 'Jim', 'John']
for person in people:
    print(f"Here comes {person}")
```

Der indirekte Nutzen der Schleifen-Variable trägt viel zur Verwirrung beim Lernen von For-Schleifen in anderen Sprachen bei. Denn die dort zentrale **Schleifen-Variable interessiert uns meist nicht**. Sie dient lediglich zum Indizieren der einzelnen Elemente. Die Nutzung herkömmlicher For-Schleifen bedingt ein Verständnis mehrerer komplexer Themen. Am Beispiel von JavaScript:

<table>
  <thead>
    <tr>
      <th>Thema</th>
      <th>Auftreten in JavaScript-For-Schleife</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Variablen-Zuweisung</td>
      <td>let i = 0</td>
    </tr>
    <tr>
      <td>Boolesche Ausdrücke</td>
      <td>i &lt; limit</td>
    </tr>
    <tr>
      <td>Inkrement-/Dekrement-Operator</td>
      <td>i++ / i--</td>
    </tr>
    <tr>
      <td>Feststellen der Größe einer Kollektion</td>
      <td>i &lt; list.length</td>
    </tr>
    <tr>
      <td>Null-basierte Indizierung von Elementen</td>
      <td>i &lt; list.length ist OK; i &lt;= list.length führt zu Off-by-one Error</td>
    </tr>
  </tbody>
</table>

Die For-Schleife in Python ist deutlich benutzerfreundlicher. Auch wenn mit 'for' dasselbe Schlüsselwort zum Einsatz kommt, handelt es sich um einen grundlegend anderen Ansatz. Anstatt eine Schleifen-Variable zu inkrementieren und damit sukzessive Elemente zu indizieren, **iterieren wir direkt über den Elementen einer Kollektion**. Die For-Loop in Python ist damit vergleichbar mit dem forEach-Konstrukt mancher Sprachen wie Ruby und JavaScript.

Geben wir zur Veranschaulichung die einzelnen Buchstaben eines Wortes aus. Innerhalb der For-Schleife wird pro Schleifen-Durchlauf ein Buchstabe des Wortes in der Variable 'letter' zur Verfügung gestellt. Das **funktioniert ohne Schleifen-Variable** und damit ohne Gefahr, einen Off-by-one Error zu produzieren. Der Code ist präzise und leicht lesbar:

```none
word = "Python"
for letter in word:
    print(letter)
```

## Wie funktioniert eine For-Schleife in Python?

Wie wir gesehen haben, löst die For-Schleife in Python elegant das Problem, **über den Elementen einer Kollektion zu iterieren**. Dabei kommen wir ohne den Umweg über eine numerische Schleifenvariable aus. Das ist toll, aber wie funktioniert das genau? Um das Wirkprinzip der For-Loop in Python zu verstehen, muss man die Konzepte des Iterable und Iterators kennen.

### Worum handelt es sich bei Iterable, Iterator und Generator?

Die **For-Schleife in Python operiert auf Objekten, die als „Iterables“ bekannt** sind. Dabei handelt es sich um Strings, Listen, Tupel und weitere, zusammengesetzte Datentypen. In den Worten der offiziellen Python-Dokumentation:

---

### Zitat

&gt; „\[An iterable is\] an object capable of returning its members one at a time“ - Quelle: https://docs.python.org/3/glossary.html#term-iterable
&gt;
&gt; Übersetzung: „\[Ein Iterable ist\] ein Objekt mit der Kapazität, seine Elemente einzeln zurückzugeben“ (übersetzt von IONOS)

---

Ein **Iterable-Objekt** hat zwei Eigenschaften:

1. Es fasst mehrere Elemente als Kollektion zusammen.
2. Es gewährt Zugriff auf die Elemente über eine „Iterator“ genannte Schnittstelle.

Zusammengenommen bedeutet dies, dass Iterables Collections sind, über deren Inhalten sich iterieren lässt. Spezifisch besitzt ein Iterable eine Methode '\_\_iter\_\_()', die einen Iterator zurückgibt. Beim Iterator handelt es sich um ein **Objekt, das auf Kommando das nächste Element des Iterable liefert**. Ferner erinnert ein Iterator die Position des zuletzt zurückgegebenen Elements innerhalb der Kollektion.

<table>
  <thead>
    <tr>
      <th>Funktion</th>
      <th>Erklärung</th>
      <th>Beispiel</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>iter(collection)</td>
      <td>Ruft Methode \_\_iter\_\_() der Collection auf</td>
      <td>it = iter("Python")</td>
    </tr>
    <tr>
      <td>next(iter)</td>
      <td>Ruft Methode \_\_next\_\_() des Iterators auf</td>
      <td>next(it)</td>
    </tr>
    <tr>
      <td>collection\[index\]</td>
      <td>Ruft Methode \_\_getitem\_\_(index) der Collection auf</td>
      <td>'Python'\[1\]</td>
    </tr>
  </tbody>
</table>

Ein Iterator liefert beim Aufruf der \_\_next\_\_()-Methode das nächste Element zurück. Wurden **alle Elemente der Collection ausgeliefert, ist der Iterator erschöpft**. Ein weiterer Aufruf von \_\_next\_\_() löst eine 'StopIteration'-Exception aus.

Betrachten wir die **Funktionsweise eines Iterators an einem Beispiel**. Wir erzeugen ein range()-Objekt, das die konsekutiven Zahlen 21 bis 23 repräsentiert. Im Anschluss erzeugen wir einen Iterator mit der iter()-Funktion und geben sukzessive Elemente mit der next()-Funktion aus. Beim letzten Aufruf wird die Exception ausgelöst, da der Iterator erschöpft ist:

```none
numbers = range(21, 24)
number = iter(numbers)
next(number)
# returns `21`
next(number)
# returns `22`
next(number)
# returns `23`
next(number)
# raises `StopIteration` exception
```

Ein Iterator gibt Zugriff auf einzelne Elemente einer Collection. Daneben kennt Python das verwandte Konzept des „Generator“. Der Unterschied liegt darin, dass ein **Generator einzelne Elemente erst beim Zugriff erzeugt**. Dies spart vor allem Speicherplatz bei der Ausführung des Programms; man spricht dabei auch von „lazy generation“.

Ein Generator in Python beruht auf einer Funktion, die die Yield-Anweisung benutzt. Diese **gibt ähnlich der Return-Anweisung ein Objekt zurück und beendet den Funktionsaufruf**. Beim erneuten Aufruf beginnt die Generator-Funktion jedoch nicht wieder von vorne, sondern läuft nach der letzten Yield-Anweisung weiter.

Schauen wir uns ein Beispiel an. Wir schreiben eine **eigene Implementation der range()-Funktion**. Dabei nutzen wir die Yield-Anweisung innerhalb einer While-Schleife, um fortlaufende Zahlen zu generieren:

```none
def my_range(start, stop):
    if stop < start:
        return None
    current = start
    while current < stop:
        yield current
        current += 1
# test
assert list(my_range(7, 9)) == list(range(7, 9))
```

### Einen Durchlauf der For-Schleife in Python überspringen und abbrechen

In der Praxis ist es manchmal notwendig, einen einzelnen Schleifen-Durchlauf zu überspringen. Wie viele andere Sprachen enthält Python die Continue-Anweisung. Beim **Aufruf von continue innerhalb des Schleifenkörpers wird die laufende Iteration abgebrochen**. Die Schleife beginnt im Anschluss sofort mit der nächsten Iteration.

Eine Continue-Anweisung **lässt sich ähnlich dem Early Return beim Funktionsaufruf nutzen**. Beispielsweise überspringen wir eine Iteration, sobald wir feststellen, dass ein Datensatz nicht über die benötigte Qualität verfügt:

```none
def process_data(data):
    for data_set in data:
        data_set.validate()
        # early continue after cheap check fails
        if not data_set.quality_ok():
            continue
        # expensive operation guarded by early continue
        data_set.process()
```

Ein weiteres Beispiel – wir geben einen Text aus und **überspringen jeden zweiten Buchstaben**:

```none
text = 'Skipping every second letter'
for index, letter in enumerate(text):
    if index % 2 != 0 and letter != ' ':
        continue
    print(letter)
```

Neben der Continue-Anweisung zum Überspringen eines Schleifen-Durchlaufs gibt es die Break-Anweisung. Ein Aufruf von break innerhalb des Schleifenkörpers **bricht die weitere Ausführung der Schleife sofort ab**. Damit hat break eine ähnliche Funktion für Schleifen wie die Return-Anweisung für Funktionen.

Häufig kommt die Break-Anweisung zum Einsatz, um Suchalgorithmen zu implementieren. Wurde innerhalb einer Schleife ein gesuchtes Element gefunden, ist es unnötig, weiter zu iterieren. Überprüfen wir analog zur any()-Funktion eine Liste auf Vorhandensein eines einzelnen True-Wertes. Wir brechen mit break ab, sobald wir fündig geworden sind:

```none
bool_list = [False, False, True, False]
for index, boolean in enumerate(bool_list):
    if boolean:
        print(f"Value at position {index + 1} is True")
        print(f"Aborting inspection of remaining {len(bool_list) - index - 1} item(s)")
        break
```

Im Zusammenhang mit der Break-Anweisung lässt sich eine For-Schleife in Python **mit einem optionalen Else-Körper versehen**. Der enthaltene Code wird ausgeführt, wenn die Schleife terminiert, ohne dass eine Break-Anweisung ausgeführt wurde:

```none
def find_element(target, collection):
    for element in collection:
        if element == target:
            print("Found what you're looking for")
            break
    else:
        print("Didn't find what you were looking for")
# test
find_element('a', 'Python')
find_element('o', 'Python')
```

For-Schleifen kommen in Python oft innerhalb von Funktionskörpern zum Einsatz. In diesem Fall ist es gebräuchlich, **statt einer Break-Anweisung eine Return-Anweisung zu verwenden**. Unser Suchalgorithmus umformuliert ohne den Einsatz von break und else:

```none
def find_element(target, collection):
    for element in collection:
        if element == target:
            print("Found what you're looking for")
            # returning breaks us out of the loop
            return element
    # we made it here without returning
    print("Didn't find what you were looking for")
    return None
# test
print(find_element('a', 'Python'))
print(find_element('o', 'Python'))
```

## Was sind die Best Practices für For-Loops in Python?

For-Loops in Python dienen in erster Linie zum **Iterieren über den Elementen einer Sequenz oder Kollektion**. Ferner existieren für viele häufige Anwendungsfälle direktere Methoden. Wir stellen wichtige Best Practices und Anti-Patterns vor. Zunächst ein Überblick zentraler Begriffe:

<table>
  <thead>
    <tr>
      <th>Begriff</th>
      <th>Erklärung</th>
      <th>Beispiel</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Collection</td>
      <td>Zusammenfassung mehrerer Elemente. Eine Collection ist ein Iterable</td>
      <td>('Walter', 'White'), \[4, 2, 6, 9\], 'Python'</td>
    </tr>
    <tr>
      <td>Iterator</td>
      <td>Schnittstelle zum Iterieren über Collections</td>
      <td>it = iter('Python')</td>
    </tr>
    <tr>
      <td>Generator</td>
      <td>Eine Funktion, die yield statt der Return-Anweisung verwendet. Ein Generator ist Iterable</td>
      <td>range(10)</td>
    </tr>
    <tr>
      <td>Comprehension</td>
      <td>Iterierender Ausdruck; erzeugt eine neue Kollektion basierend auf einem Iterable</td>
      <td>\[num \*\* 2 for num in range(10)\]</td>
    </tr>
  </tbody>
</table>

### Direkt über den Elementen einer Kollektion iterieren

Ein **häufiger Fehler unerfahrener Python-Programmierer** besteht darin, die For-Loop in Python zu missbrauchen. Wie in anderen Sprachen üblich, nutzen sie die len()-Funktion als Limit der range()-Funktion, um eine numerische Schleifen-Variable zu erzeugen. Sie indizieren damit die einzelnen Elemente der Kollektion:

```none
word = 'Python'
for i in range(len(word)):
    print(word[i])
```

Dieses Anti-Pattern ist **aus gutem Grund als unpythonisch verpönt**. Denn es ist besser, mit der For-Loop in Python direkt über den Elementen der Kollektion zu iterieren:

```none
word = 'Python'
for letter in word:
    print(letter)
```

### Elemente einer Kollektion mit enumerate() samt Index aufzählen

Manchmal **benötigt man den Index eines Elements innerhalb der Collection**. Anstatt den Index als Schleifen-Variable zu erzeugen, nutzen wir die enumerate()-Funktion. Diese gibt das Tupel (Index, Element) zurück. Dabei ist zu beachten, dass der Index bei null zu zählen anfängt:

```none
names = ["Jim", "Jack", "John"]
for index, name in enumerate(names):
    print(f"{index + 1}. {name}")
```

### Mit der zip()-Funktion über Tupeln von Elementen iterieren

Ein weiteres häufig anzutreffendes Szenario ist das **gleichzeitige Iterieren über den Elementen zwei gleich langer Collections**. Der pythonische Ansatz benutzt die zip()-Funktion. Diese nimmt zwei gleich lange Collections entgegen und gibt sukzessive 2-Tupel zurück:

```none
people = ('Jim', 'Jack', 'John')
ages = (42, 69, 13)
# ascertain both collections are same length
assert len(people) == len(ages)
# iterate over tuples of (person, age)
for person, age in zip(people, ages):
    print(f"{person} is {age} years old")
```

### Mit der range()-Funktion eine numerische Schleifen-Variable erzeugen

Normalerweise werden For-Loops in Python eingesetzt, um über Elementen einer Kollektion zu iterieren. Das **Inkrementieren einer Ganzzahl mit einer For-Schleife** ist in Python eher ein Spezialfall. Der korrekte Weg besteht darin, mit der range()-Funktion ein Range-Objekt zu konstruieren und über diesem zu iterieren:

```none
for counter in range(10):
    print(counter)
```

### Mit dem in-Operator testen, ob eine Kollektion ein Element enthält

Das Auffinden eines bestimmten Elements innerhalb einer Kollektion gehört zum Standard-Repertoire eines Programmierers. Normalerweise kommt eine Funktion zum Einsatz, die über den Elementen iteriert und dabei **jedes Element auf Gleichheit mit dem gesuchten überprüft**. Wurde das Element gefunden, wird die Iteration abgebrochen.

In Python existiert für diesen häufigen Fall der in-Operator. Der Operator **überprüft, ob die Kollektion das gesuchte Element enthält**, und liefert einen entsprechenden booleschen Wert zurück:

```none
'a' in 'Python'
'y' in 'Python'
```

### Mit der list()-Funktion aus einem Iterable eine Liste erzeugen

Anders als in vielen anderen Sprachen ist es unnötig, eine For-Schleife in Python einzusetzen, um die **Buchstaben eines Strings einzeln in eine Liste zu schreiben**. Stattdessen nutzen wir die list()-Funktion, um ein Iterable in eine Liste von Elementen zu konvertieren. Schauen wir uns beide Ansätze an einem Beispiel an. Wir iterieren über den Buchstaben eines Wortes und fügen diese einer leeren Liste hinzu:

```none
word = 'Python'
letters = []
for letter in word:
    letters.append(letter)
```

Den Aufwand können wir uns sparen. Wir **erzeugen die Liste mit der list()-Funktion direkt**. Im selben Zuge überprüfen wir mit der Assert-Anweisung, dass beide Methoden dasselbe Resultat liefern:

```none
assert list(word) == letters
```

Ein weiteres Beispiel: Wir **erzeugen die Liste der Zahlen null bis neun**. Als Basis dient ein Range-Objekt als Iterable:

```none
list(range(10))
```

Neben Listen lassen sich auch **Mengen**, auf Englisch „Sets“, aus einem Iterable erzeugen. Beispielshalber erzeugen wir ein Set, das die in einem Satz enthaltenen Buchstaben widerspiegelt. Im Anschluss überprüfen wir mit dem in-Operator, dass die Menge der Buchstaben kein 'a' enthält:

```none
alphabet = set('Python is not hyped')
assert 'a' not in alphabet
```

## For-Loops in Python mit Comprehensions ersetzen

Ein häufiger Nutzen von For-Schleifen in Python besteht darin, die Elemente einer Kollektion zu modifizieren. Ggf. möchten wir **basierend auf einer Kollektion neue Werte errechnen** oder bestimmte Elemente nach einem Muster filtern. Dem imperativen Programmierstil folgend beschreiben wir die einzelnen Schritte:

1. Mit For-Schleife über der Kollektion iterieren.
2. Jedes Element verarbeiten.
3. Dabei ggf. Untermenge der Elemente zu neuer Kollektion zusammenfassen.

Für simple Modifikationen ist dies recht aufwendig. Funktionale Sprachen machen es vor, dass es auch einfacher geht. Glücklicherweise kennt Python das Konzept der „Comprehensions“. Comprehensions können **simple Anwendungen der For-Schleife in Python ersetzen**. Sie sind dabei performanter als äquivalente Anwendungen einer For-Schleife.

Ein **Comprehension erzeugt eine ggf. modifizierte Kollektion basierend auf einem Iterable**. Dabei kommt eine knappe, ausdrucksstarke Syntax zum Einsatz. Betrachten wir die generelle Syntax einer List Comprehension. Wir schreiben den Ausdruck zwischen eckige Klammern. Eine Operation wird auf den Elementen einer Kollektion ausgeführt; jedes Element wird dabei in eine neue Liste kopiert:

```none
[ operation(element) for element in collection ]
```

Ferner lassen sich **Elemente nach bestimmten Mustern filtern**. Zum Einsatz kommt ein optionales if und eine Bedingung:

```none
[ operation(element) for element in collection if condition(element) ]
```

Betrachten wir im Anschluss ein Beispiel für eine **For-Schleife in Python, die sich durch eine Comprehension ersetzen lässt**. Wir haben eine Liste mit Zahlen und möchten die dazu korrespondierende Liste an Quadratzahlen berechnen:

```none
numbers = [2, 3, 5, 9, 17]
```

Wir **erzeugen eine leere Liste und befüllen diese innerhalb einer For-Schleife** mit den Quadraten:

```none
squares = []
for number in numbers:
    squares.append(number ** 2)
```

Einfacher ausdrücken lässt sich die **Liste mit Quadratzahlen als Comprehension**:

```none
squares_comp = [number ** 2 for number in numbers]
```

Im Anschluss stellen wir mithilfe der Assert-Anweisung sicher, dass **beide Methoden dasselbe Ergebnis** liefern:

```none
assert squares == squares_comp
```

Ein weiteres Beispiel: Wir möchten **Kleinbuchstaben aus einem String extrahieren**. Als Eingabe erzeugen wir eine Liste von Buchstaben mit gemischter Groß- und Kleinschreibung:

```none
word = list("PyThoN")
```

Der herkömmliche Weg, die Kleinbuchstaben zu extrahieren, besteht darin, über den Buchstaben zu iterieren. Wir **testen jeden Buchstaben mit der islower()-Funktion** und fügen ihn bei positivem Resultat zu einer anfangs leeren Liste hinzu:

```none
lowers = []
for letter in word:
    if letter.islower():
        lowers.append(letter)
```

Diese For-Schleife können wir uns in Python sparen. Wir benutzen stattdessen eine **Comprehension**, die nur Kleinbuchstaben aus der ursprünglichen Liste kopiert:

```none
lowers_comp = [ letter for letter in word if letter.islower() ]
```

Wiederum **überprüfen wir die Gleichheit der beiden Methoden** mittels Assert-Anweisung:

```none
assert lowers == lowers_comp
```


This is a markdown version of: [https://www.ionos.de/digitalguide/websites/web-entwicklung/for-loop-in-python/](https://www.ionos.de/digitalguide/websites/web-entwicklung/for-loop-in-python/) for AI/LLM consumption.