Python & AI Tutorials Logo
Python Programmierung

14. Listen: Geordnete Sammlungen von Elementen

Bisher haben wir in diesem Buch mit einzelnen Dateneinheiten gearbeitet: einzelnen Zahlen, Strings und booleschen Werten. Aber echte Programme müssen oft mit Sammlungen zusammengehöriger Elemente arbeiten – eine Liste von Schülernamen, eine Reihe von Temperaturmessungen, eine Sammlung von Produktpreisen oder eine Sequenz von Benutzerbefehlen. Pythons Liste (list) ist das grundlegende Werkzeug zum Speichern und Arbeiten mit geordneten Datensammlungen.

Eine Liste ist eine Sequenz (sequence), die mehrere Elemente in einer bestimmten Reihenfolge enthalten kann. Anders als Strings (die nur Zeichen enthalten können) können Listen beliebige Datentypen enthalten: Zahlen, Strings, boolesche Werte oder sogar andere Listen. Listen sind außerdem veränderbar (mutable), das heißt, Sie können ihren Inhalt nach der Erstellung ändern – Elemente hinzufügen, Elemente entfernen oder vorhandene Elemente ändern.

In diesem Kapitel erkunden wir, wie man Listen erstellt, auf ihre Elemente zugreift, sie verändert und sie zur Lösung praktischer Programmierprobleme verwendet. Am Ende werden Sie verstehen, warum Listen eine der leistungsstärksten und am häufigsten verwendeten Datenstrukturen in Python sind.

14.1) Listen erstellen und auf Elemente zugreifen

14.1.1) Listen mit eckigen Klammern erstellen

Die häufigste Art, eine Liste zu erstellen, besteht darin, Elemente in eckige Klammern [] zu setzen, wobei die Elemente durch Kommas getrennt sind. Hier ist ein einfaches Beispiel:

python
# Eine Liste mit Schülernamen
students = ["Alice", "Bob", "Charlie", "Diana"]
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

Beachten Sie, wie Python die Liste anzeigt: Es zeigt die eckigen Klammern und setzt Anführungszeichen um jeden String. Das ist die Darstellung (representation) der Liste – wie Python Ihnen zeigt, was enthalten ist.

Listen können beliebige Datentypen enthalten. Hier ist eine Liste von Testergebnissen:

python
# Eine Liste mit ganzzahligen Punktzahlen
scores = [85, 92, 78, 95, 88]
print(scores)  # Output: [85, 92, 78, 95, 88]

Sie können sogar verschiedene Typen in derselben Liste mischen, auch wenn das in der Praxis weniger üblich ist:

python
# Eine Liste mit gemischten Typen (weniger üblich, aber gültig)
mixed_data = ["Alice", 25, True, 3.14]
print(mixed_data)  # Output: ['Alice', 25, True, 3.14]

Eine leere Liste (empty list) enthält keine Elemente und wird nur mit den eckigen Klammern erstellt:

python
# Eine leere Liste
empty = []
print(empty)  # Output: []
print(len(empty))  # Output: 0

Die Funktion len(), die wir mit Strings verwendet haben, funktioniert auch mit Listen – sie gibt die Anzahl der Elemente in der Liste zurück.

14.1.2) Listenreihenfolge und Positionen verstehen

Listen behalten die Reihenfolge (order) bei, in der Sie Elemente hinzufügen. Das erste Element, das Sie einfügen, bleibt zuerst, das zweite bleibt zweites und so weiter. Diese Reihenfolge ist entscheidend, weil sie Ihnen ermöglicht, auf bestimmte Elemente anhand ihrer Position (position) (auch Index (index) genannt) zuzugreifen.

Python verwendet eine nullbasierte Indizierung (zero-based indexing): Das erste Element befindet sich an Position 0, das zweite an Position 1 und so weiter. Das wirkt am Anfang vielleicht ungewöhnlich, ist aber eine Konvention, die von vielen Programmiersprachen verwendet wird.

Liste: ['Alice', 'Bob', 'Charlie', 'Diana']

Index 0: 'Alice'

Index 1: 'Bob'

Index 2: 'Charlie'

Index 3: 'Diana'

Schauen wir uns an, wie das in der Praxis funktioniert:

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Auf den ersten Schüler zugreifen (Index 0)
first_student = students[0]
print(first_student)  # Output: Alice
 
# Auf den dritten Schüler zugreifen (Index 2)
third_student = students[2]
print(third_student)  # Output: Charlie

Beachten Sie, dass wir für den dritten Schüler den Index 2 verwenden, nicht 3. Das liegt daran, dass das Zählen bei 0 beginnt.

14.1.3) Auf Elemente mit positiven Indizes zugreifen

Um auf ein Listenelement zuzugreifen, schreiben Sie den Listennamen gefolgt vom Index in eckigen Klammern: list_name[index]. Der Index muss eine ganze Zahl innerhalb des gültigen Bereichs sein (0 bis len(list) - 1).

Hier ist ein praktisches Beispiel mit Produktpreisen:

python
# Produktpreise in Dollar
prices = [19.99, 24.50, 15.75, 32.00, 8.99]
 
# Auf bestimmte Preise zugreifen
first_price = prices[0]
last_index = len(prices) - 1  # Den letzten gültigen Index berechnen
last_price = prices[last_index]
 
print(f"First product costs: ${first_price}")  # Output: First product costs: $19.99
print(f"Last product costs: ${last_price}")    # Output: Last product costs: $8.99

Warum verwenden wir len(prices) - 1 als letzten Index? Weil eine Liste mit 5 Elementen die Indizes 0, 1, 2, 3, 4 hat – der letzte gültige Index ist immer um eins kleiner als die Länge.

Sie können Indizes auch in Ausdrücken und Berechnungen verwenden:

python
scores = [85, 92, 78, 95, 88]
 
# Den Durchschnitt der ersten drei Punktzahlen berechnen
first_three_average = (scores[0] + scores[1] + scores[2]) / 3
print(f"Average of first three: {first_three_average}")  # Output: Average of first three: 85.0

14.1.4) Negative Indizes: Vom Ende aus zählen

Python bietet eine praktische Funktion: negative Indizes (negative indices) ermöglichen es Ihnen, auf Elemente vom Ende der Liste aus zuzugreifen. Index -1 bezieht sich auf das letzte Element, -2 auf das vorletzte und so weiter.

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Vom Ende aus zugreifen
last_student = students[-1]
second_to_last = students[-2]
 
print(last_student)      # Output: Diana
print(second_to_last)    # Output: Charlie

Das ist besonders nützlich, wenn Sie das letzte Element wollen, aber len(list) - 1 nicht berechnen möchten:

python
prices = [19.99, 24.50, 15.75, 32.00, 8.99]
 
# Diese beiden Ansätze sind gleichwertig
last_price_method1 = prices[len(prices) - 1]
last_price_method2 = prices[-1]
 
print(last_price_method1)  # Output: 8.99
print(last_price_method2)  # Output: 8.99

So ordnen sich positive und negative Indizes denselben Elementen zu:

Liste: ['Alice', 'Bob', 'Charlie', 'Diana']

Positiv: 0, 1, 2, 3

Negativ: -4, -3, -2, -1

Beide beziehen sich auf dieselben Elemente

14.1.5) Was passiert bei ungültigen Indizes?

Wenn Sie versuchen, auf einen Index zuzugreifen, der nicht existiert, löst Python einen IndexError (IndexError) aus:

python
students = ["Alice", "Bob", "Charlie"]
 
# WARNUNG: Diese Liste hat die Indizes 0, 1, 2 (oder -3, -2, -1) - nur zur Demonstration
# Der Zugriff auf Index 3 verursacht einen Fehler
# PROBLEM: Index 3 existiert nicht in einer Liste mit 3 Elementen
# print(students[3])  # IndexError: list index out of range

Dieser Fehler ist Pythons Art, Ihnen mitzuteilen, dass Sie nach einem Element gefragt haben, das nicht vorhanden ist.

14.2) Listenindizierung und Slicing

14.2.1) Grundlagen des List-Slicing verstehen

So wie wir Strings schneiden (wie wir in Kapitel 5 gelernt haben), können wir auch Listen slicen (slice), um Teile daraus zu extrahieren. Ein Slice erstellt eine neue Liste, die eine Teilmenge der Elemente der ursprünglichen Liste enthält. Die Syntax lautet list[start:stop], wobei start der Index ist, an dem der Slice beginnt (inklusive), und stop der Index ist, an dem er endet (exklusive).

python
numbers = [10, 20, 30, 40, 50, 60, 70]
 
# Elemente von Index 1 bis (ohne) Index 4 holen
subset = numbers[1:4]
print(subset)  # Output: [20, 30, 40]

Der Slice [1:4] umfasst die Indizes 1, 2 und 3, endet aber vor Index 4. Diese Regel „stop ist exklusiv“ ist dieselbe wie beim String-Slicing.

Schauen wir uns ein praktisches Beispiel mit Schülernamen an:

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]
 
# Die ersten drei Schüler holen
first_three = students[0:3]
print(first_three)  # Output: ['Alice', 'Bob', 'Charlie']
 
# Schüler von Index 2 bis 4 holen
middle_group = students[2:5]
print(middle_group)  # Output: ['Charlie', 'Diana', 'Eve']

14.2.2) Start oder Stop bei Slices weglassen

Sie können den Startindex weglassen, um vom Anfang aus zu slicen, oder den Stopindex weglassen, um bis zum Ende zu slicen:

python
scores = [85, 92, 78, 95, 88, 91, 87]
 
# Vom Anfang bis Index 3
first_few = scores[:3]
print(first_few)  # Output: [85, 92, 78]
 
# Von Index 4 bis zum Ende
last_few = scores[4:]
print(last_few)  # Output: [88, 91, 87]
 
# Die gesamte Liste (vom Anfang bis zum Ende)
all_scores = scores[:]
print(all_scores)  # Output: [85, 92, 78, 95, 88, 91, 87]

Der Slice [:] erstellt eine Kopie (copy) der gesamten Liste. Das ist nützlich, wenn Sie mit einem Duplikat arbeiten möchten, ohne das Original zu verändern – wir werden das in Abschnitt 14.6 genauer untersuchen.

14.2.3) Negative Indizes in Slices verwenden

Negative Indizes funktionieren in Slices genauso wie beim Zugriff auf einzelne Elemente. Das ist besonders nützlich, um Elemente vom Ende aus zu holen:

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]
 
# Die letzten drei Schüler holen
last_three = students[-3:]
print(last_three)  # Output: ['Diana', 'Eve', 'Frank']
 
# Alle außer den letzten beiden Schülern holen
all_but_last_two = students[:-2]
print(all_but_last_two)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']
 
# Vom drittletzten bis zum vorletzten holen
middle_from_end = students[-3:-1]
print(middle_from_end)  # Output: ['Diana', 'Eve']

14.2.4) Slicing mit einem Step-Wert

Sie können einen dritten Parameter hinzufügen, um den Schritt (step) zu steuern (wie viele Indizes zwischen Elementen übersprungen werden). Die vollständige Syntax lautet list[start:stop:step]:

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
# Jede zweite Zahl ab Index 0
evens = numbers[0:10:2]
print(evens)  # Output: [0, 2, 4, 6, 8]
 
# Jede dritte Zahl ab Index 1
every_third = numbers[1:10:3]
print(every_third)  # Output: [1, 4, 7]

Sie können auch einen negativen Schritt (negative step) verwenden, um die Liste umzukehren:

python
numbers = [1, 2, 3, 4, 5]
 
# Die Liste umkehren
reversed_numbers = numbers[::-1]
print(reversed_numbers)  # Output: [5, 4, 3, 2, 1]

Der Slice [::-1] bedeutet „am Ende starten, bis zum Anfang gehen, rückwärts in Schritten von 1“. Das ist ein gängiges Python-Idiom zum Umkehren von Sequenzen.

14.2.5) Slices verursachen nie IndexError

Im Gegensatz zum Zugriff auf ein einzelnes Element ist Slicing sehr tolerant. Wenn Sie Indizes außerhalb des Bereichs der Liste angeben, passt Python sie einfach an:

python
numbers = [10, 20, 30, 40, 50]
 
# Mehr anfordern als vorhanden ist
extended_slice = numbers[2:100]
print(extended_slice)  # Output: [30, 40, 50]
 
# Jenseits des Endes starten
empty_slice = numbers[10:20]
print(empty_slice)  # Output: []

Dieses Verhalten ist nützlich, weil es bedeutet, dass Sie sich beim Slicing keine Sorgen um exakte Grenzen machen müssen – Python behandelt Randfälle elegant.

14.3) Listen verändern und häufige Listenmethoden

14.3.1) Listen sind veränderbar: Elemente ändern

Anders als Strings, die unveränderlich sind, sind Listen sind veränderbar (lists are mutable) – Sie können ihren Inhalt nach der Erstellung ändern. Sie können einzelne Elemente ändern, indem Sie neuen Werten bestimmte Indizes zuweisen:

python
# Mit einer Liste von Preisen beginnen
prices = [19.99, 24.50, 15.75, 32.00]
print(prices)  # Output: [19.99, 24.5, 15.75, 32.0]
 
# Den zweiten Preis aktualisieren (Index 1)
prices[1] = 22.99
print(prices)  # Output: [19.99, 22.99, 15.75, 32.0]
 
# Den letzten Preis mithilfe negativer Indizierung aktualisieren
prices[-1] = 29.99
print(prices)  # Output: [19.99, 22.99, 15.75, 29.99]

Diese Veränderbarkeit ist mächtig – sie bedeutet, dass Sie Daten direkt aktualisieren können, ohne neue Listen zu erstellen. Sie bedeutet jedoch auch, dass Sie bei unbeabsichtigten Änderungen vorsichtig sein müssen, was wir in Abschnitt 14.6 besprechen werden.

14.3.2) Elemente mit append() hinzufügen

Die Methode append() fügt ein einzelnes Element am Ende (end) einer Liste hinzu. Das ist eine der am häufigsten verwendeten Listenoperationen:

python
# Mit einem leeren Einkaufskorb starten
cart = []
print(cart)  # Output: []
 
# Elemente nacheinander hinzufügen
cart.append("Milk")
print(cart)  # Output: ['Milk']
 
cart.append("Bread")
print(cart)  # Output: ['Milk', 'Bread']
 
cart.append("Eggs")
print(cart)  # Output: ['Milk', 'Bread', 'Eggs']

Beachten Sie, dass append() die Liste direkt (in place) verändert – es gibt keine neue Liste zurück. Die Methode gibt None zurück, daher müssen Sie das Ergebnis nicht zuweisen:

python
scores = [85, 92, 78]
result = scores.append(95)
 
print(scores)   # Output: [85, 92, 78, 95]
print(result)   # Output: None

14.3.3) Elemente an bestimmten Positionen mit insert() einfügen

Während append() immer am Ende hinzufügt, ermöglicht insert() das Einfügen eines Elements an jeder Position. Die Syntax lautet list.insert(index, item):

python
students = ["Alice", "Charlie", "Diana"]
print(students)  # Output: ['Alice', 'Charlie', 'Diana']
 
# "Bob" bei Index 1 einfügen (zwischen Alice und Charlie)
students.insert(1, "Bob")
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

Wenn Sie an einem Index einfügen, rückt das Element, das aktuell an dieser Position steht (und alle danach), nach rechts:

python
numbers = [10, 20, 30, 40]
print(numbers)  # Output: [10, 20, 30, 40]
 
# 25 bei Index 2 einfügen
numbers.insert(2, 25)
print(numbers)  # Output: [10, 20, 25, 30, 40]

Sie können am Anfang einfügen, indem Sie Index 0 verwenden:

python
priorities = ["Medium", "Low"]
priorities.insert(0, "High")
print(priorities)  # Output: ['High', 'Medium', 'Low']

Wenn Sie einen Index angeben, der größer als die Länge der Liste ist, fügt insert() das Element einfach am Ende hinzu (wie append()):

python
items = [1, 2, 3]
items.insert(100, 4)
print(items)  # Output: [1, 2, 3, 4]

14.3.4) Elemente mit remove() entfernen

Die Methode remove() entfernt das erste Vorkommen (first occurrence) eines bestimmten Werts aus der Liste:

python
fruits = ["apple", "banana", "cherry", "banana", "date"]
print(fruits)  # Output: ['apple', 'banana', 'cherry', 'banana', 'date']
 
# Die erste "banana" entfernen
fruits.remove("banana")
print(fruits)  # Output: ['apple', 'cherry', 'banana', 'date']

Beachten Sie, dass nur die erste „banana“ entfernt wurde – die zweite bleibt. Wenn Sie versuchen, einen Wert zu entfernen, der nicht existiert, löst Python einen ValueError (ValueError) aus:

python
numbers = [10, 20, 30]
# WARNUNG: Versuch, einen nicht vorhandenen Wert zu entfernen - nur zur Demonstration
# PROBLEM: 40 ist nicht in der Liste
# numbers.remove(40)  # ValueError: list.remove(x): x not in list

Um diesen Fehler zu vermeiden, können Sie prüfen, ob das Element existiert, bevor Sie es entfernen:

python
cart = ["Milk", "Bread", "Eggs"]
item_to_remove = "Butter"
 
if item_to_remove in cart:
    cart.remove(item_to_remove)
    print(f"Removed {item_to_remove}")
else:
    print(f"{item_to_remove} not in cart")
# Output: Butter not in cart

14.3.5) Elemente mit pop() entfernen und zurückgeben

Die Methode pop() entfernt ein Element an einem bestimmten Index und gibt (return) es zurück. Wenn Sie keinen Index angeben, entfernt und gibt sie das letzte Element zurück:

python
scores = [85, 92, 78, 95, 88]
 
# Die letzte Punktzahl entfernen und erhalten
last_score = scores.pop()
print(f"Removed: {last_score}")  # Output: Removed: 88
print(scores)  # Output: [85, 92, 78, 95]
 
# Die Punktzahl bei Index 1 entfernen und erhalten
second_score = scores.pop(1)
print(f"Removed: {second_score}")  # Output: Removed: 92
print(scores)  # Output: [85, 78, 95]

Das ist nützlich, wenn Sie Elemente aus einer Liste nacheinander verarbeiten müssen:

python
tasks = ["Write code", "Test code", "Deploy code"]
 
while len(tasks) > 0:
    current_task = tasks.pop(0)  # Vom Anfang entfernen
    print(f"Working on: {current_task}")
 
# Output:
# Working on: Write code
# Working on: Test code
# Working on: Deploy code
 
print(tasks)  # Output: []

14.3.6) Listen mit extend() erweitern

Die Methode extend() fügt alle Elemente aus einer anderen Liste (oder einem beliebigen Iterable) an das Ende der aktuellen Liste hinzu:

python
primary_colors = ["red", "blue", "yellow"]
secondary_colors = ["green", "orange", "purple"]
 
# Alle Sekundärfarben zu den Primärfarben hinzufügen
primary_colors.extend(secondary_colors)
print(primary_colors)
# Output: ['red', 'blue', 'yellow', 'green', 'orange', 'purple']

Das unterscheidet sich von append(), das die gesamte Liste als ein einzelnes Element hinzufügen würde:

python
colors1 = ["red", "blue"]
colors2 = ["green", "orange"]
 
# append verwenden (fügt die Liste als ein Element hinzu)
colors1.append(colors2)
print(colors1)  # Output: ['red', 'blue', ['green', 'orange']]
 
# extend verwenden (fügt jedes Element einzeln hinzu)
colors3 = ["red", "blue"]
colors3.extend(colors2)
print(colors3)  # Output: ['red', 'blue', 'green', 'orange']

14.3.7) Listen mit sort() und sorted() sortieren

Python bietet zwei Möglichkeiten, Listen zu sortieren. Die Methode sort() sortiert die Liste direkt (in place) (und verändert das Original):

python
scores = [78, 95, 85, 92, 88]
scores.sort()
print(scores)  # Output: [78, 85, 88, 92, 95]

Um absteigend zu sortieren, verwenden Sie den Parameter reverse:

python
scores = [78, 95, 85, 92, 88]
scores.sort(reverse=True)
print(scores)  # Output: [95, 92, 88, 85, 78]

Die Funktion sorted() (die wir in Kapitel 38 genauer untersuchen werden) erstellt eine neue sortierte Liste (new sorted list), ohne das Original zu verändern:

python
original = [78, 95, 85, 92, 88]
sorted_scores = sorted(original)
 
print(original)       # Output: [78, 95, 85, 92, 88]
print(sorted_scores)  # Output: [78, 85, 88, 92, 95]

Sortieren funktioniert auch mit Strings, in alphabetischer Reihenfolge:

python
names = ["Charlie", "Alice", "Diana", "Bob"]
names.sort()
print(names)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

14.3.8) Listen mit reverse() umkehren

Die Methode reverse() kehrt die Liste direkt (in place) um:

python
numbers = [1, 2, 3, 4, 5]
numbers.reverse()
print(numbers)  # Output: [5, 4, 3, 2, 1]

Das unterscheidet sich vom Sortieren in umgekehrter Reihenfolge – reverse() dreht einfach die aktuelle Reihenfolge um, wie auch immer sie ist:

python
mixed = [3, 1, 4, 1, 5]
mixed.reverse()
print(mixed)  # Output: [5, 1, 4, 1, 3]

Denken Sie daran, dass Sie eine Liste auch mit Slicing umkehren können: list[::-1]. Der Unterschied ist, dass Slicing eine neue Liste erstellt, während reverse() das Original verändert.

14.3.9) Elemente mit index() und count() finden

Die Methode index() gibt die Position des ersten Vorkommens eines Werts zurück:

python
students = ["Alice", "Bob", "Charlie", "Diana", "Bob"]
 
# Herausfinden, wo "Charlie" ist
position = students.index("Charlie")
print(f"Charlie is at index {position}")  # Output: Charlie is at index 2
 
# Das erste "Bob" finden
bob_position = students.index("Bob")
print(f"Bob is at index {bob_position}")  # Output: Bob is at index 1

Wenn der Wert nicht existiert, löst index() einen ValueError (ValueError) aus:

python
students = ["Alice", "Bob", "Charlie"]
# WARNUNG: Versuch, einen nicht vorhandenen Wert zu finden - nur zur Demonstration
# PROBLEM: 'Eve' ist nicht in der Liste
# position = students.index("Eve")  # ValueError: 'Eve' is not in list

Die Methode count() gibt zurück, wie oft ein Wert vorkommt:

python
numbers = [1, 2, 3, 2, 4, 2, 5]
twos = numbers.count(2)
print(f"The number 2 appears {twos} times")  # Output: The number 2 appears 3 times
 
# count kann 0 zurückgeben, wenn das Element nicht existiert
sixes = numbers.count(6)
print(f"The number 6 appears {sixes} times")  # Output: The number 6 appears 0 times

14.3.10) Alle Elemente mit clear() entfernen

Die Methode clear() entfernt alle Elemente aus einer Liste und lässt sie leer zurück:

python
cart = ["Milk", "Bread", "Eggs", "Butter"]
print(cart)  # Output: ['Milk', 'Bread', 'Eggs', 'Butter']
 
cart.clear()
print(cart)  # Output: []
print(len(cart))  # Output: 0

Das ist gleichbedeutend damit, eine leere Liste zuzuweisen, aber clear() macht die Absicht deutlicher.

14.4) Listenelemente mit del löschen

14.4.1) del verwenden, um Elemente nach Index zu entfernen

Die Anweisung del kann Listenelemente an bestimmten Indizes löschen:

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve"]
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']
 
# Das Element bei Index 2 löschen
del students[2]
print(students)  # Output: ['Alice', 'Bob', 'Diana', 'Eve']

Anders als pop() gibt del den entfernten Wert nicht zurück – es löscht ihn einfach. Das ist nützlich, wenn Sie ein Element entfernen möchten, es aber nicht weiter verwenden müssen:

python
scores = [85, 92, 78, 95, 88]
 
# Die niedrigste Punktzahl entfernen (bei Index 2)
del scores[2]
print(scores)  # Output: [85, 92, 95, 88]

Sie können auch negative Indizes mit del verwenden:

python
tasks = ["Task 1", "Task 2", "Task 3", "Task 4"]
 
# Die letzte Aufgabe löschen
del tasks[-1]
print(tasks)  # Output: ['Task 1', 'Task 2', 'Task 3']

14.4.2) Slices mit del löschen

Die Anweisung del kann ganze Slices auf einmal entfernen:

python
numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers)  # Output: [10, 20, 30, 40, 50, 60, 70]
 
# Elemente von Index 2 bis 4 löschen (Indizes 2, 3, 4)
del numbers[2:5]
print(numbers)  # Output: [10, 20, 60, 70]

Das ist besonders nützlich, um Bereiche von Elementen zu entfernen:

python
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
# Die ersten drei Elemente entfernen
del data[:3]
print(data)  # Output: [4, 5, 6, 7, 8, 9, 10]
 
# Die letzten zwei Elemente entfernen
del data[-2:]
print(data)  # Output: [4, 5, 6, 7, 8]

Sie können sogar jedes zweite Element mit Step-Slicing löschen:

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
# Jedes zweite Element löschen
del numbers[::2]
print(numbers)  # Output: [1, 3, 5, 7, 9]

14.4.3) del, remove() und pop() vergleichen

Klären wir, wann Sie welche Löschmethode verwenden:

python
# Beispiel-Liste zum Vergleich
items = ["apple", "banana", "cherry", "date", "elderberry"]
 
# remove() verwenden, wenn Sie den WERT kennen, der gelöscht werden soll
items_copy1 = items.copy()
items_copy1.remove("cherry")  # Entfernt die erste "cherry"
print(items_copy1)  # Output: ['apple', 'banana', 'date', 'elderberry']
 
# pop() verwenden, wenn Sie den INDEX kennen und den Wert brauchen
items_copy2 = items.copy()
removed_item = items_copy2.pop(2)  # Entfernt und gibt das Element bei Index 2 zurück
print(f"Removed: {removed_item}")  # Output: Removed: cherry
print(items_copy2)  # Output: ['apple', 'banana', 'date', 'elderberry']
 
# del verwenden, wenn Sie den INDEX kennen, aber den Wert nicht brauchen
items_copy3 = items.copy()
del items_copy3[2]  # Entfernt einfach das Element bei Index 2
print(items_copy3)  # Output: ['apple', 'banana', 'date', 'elderberry']

14.5) Über Listen mit for-Schleifen iterieren

14.5.1) Grundlegende Listeniteration

Eine der häufigsten Operationen mit Listen besteht darin, jedes Element der Reihe nach zu verarbeiten. Die for-Schleife(for loop) (die wir in Kapitel 12 gelernt haben) ist dafür perfekt:

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Jeden Schüler verarbeiten
for student in students:
    print(f"Hello, {student}!")
 
# Output:
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!
# Hello, Diana!

Die Schleifenvariable (student in diesem Fall) nimmt der Reihe nach jeden Wert aus der Liste an. Sie können diese Variable sinnvoll benennen:

python
scores = [85, 92, 78, 95, 88]
 
# Die Note für jede Punktzahl berechnen und anzeigen
for score in scores:
    if score >= 90:
        grade = "A"
    elif score >= 80:
        grade = "B"
    else:
        grade = "C"
    print(f"Score {score} is a {grade}")
 
# Output:
# Score 85 is a B
# Score 92 is a A
# Score 78 is a C
# Score 95 is a A
# Score 88 is a B

14.5.2) Zusammengehörige Elemente aus mehreren Listen verarbeiten

Manchmal müssen Sie mit zusammengehörigen Daten arbeiten, die in separaten Listen gespeichert sind. Wir werden die Funktion zip() in Kapitel 38 im Detail kennenlernen, aber hier ist eine kurze Vorschau darauf, wie sie beim Verarbeiten entsprechender Elemente helfen kann:

python
# Wir werden zip() in Kapitel 38 lernen, aber vorerst ist hier ein einfaches Beispiel
students = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
 
# Entsprechende Paare verarbeiten
for student, score in zip(students, scores):
    print(f"{student} scored {score}")
 
# Output:
# Alice scored 85
# Bob scored 92
# Charlie scored 78

Die Funktion zip() paart Elemente aus mehreren Listen, was nützlich ist, wenn Sie zusammengehörige Daten in separaten Listen haben. Wir werden dies und andere Iterationswerkzeuge in Kapitel 38 ausführlich untersuchen.

14.6) Listen kopieren und gemeinsame Referenzen vermeiden

14.6.1) Listenreferenzen verstehen

Wenn Sie eine Liste einer Variablen zuweisen, erstellt Python keine Kopie der Liste – es erstellt eine Referenz (reference) auf dasselbe Listenobjekt im Speicher. Das bedeutet, dass mehrere Variablen auf dieselbe Liste verweisen können:

python
original = [1, 2, 3]
reference = original  # Beide Variablen zeigen auf dieselbe Liste
 
# Änderungen über eine Variable wirken sich auf die andere aus
reference.append(4)
print(original)   # Output: [1, 2, 3, 4]
print(reference)  # Output: [1, 2, 3, 4]

Dieses Verhalten kann überraschend sein, wenn Sie erwarten, dass reference eine unabhängige Kopie ist. Sehen wir uns an, warum das wichtig ist:

python
# Szenario: Sie möchten Änderungen an einem Einkaufskorb nachverfolgen
cart = ["Milk", "Bread"]
backup = cart  # Versuch, den ursprünglichen Zustand zu speichern
 
# Weitere Elemente hinzufügen
cart.append("Eggs")
cart.append("Butter")
 
# Das "backup" prüfen
print(backup)  # Output: ['Milk', 'Bread', 'Eggs', 'Butter']

Das Backup hat sich ebenfalls geändert! Das liegt daran, dass backup und cart zwei Namen für dasselbe Listenobjekt sind.

Variable: cart

List Object: ⦗'Milk', 'Bread', 'Eggs', 'Butter'⦘

Variable: backup

14.6.2) Unabhängige Kopien mit Slicing erstellen

Um eine wirklich unabhängige Kopie zu erstellen, verwenden Sie Slicing mit [:]:

python
original = [1, 2, 3]
copy = original[:]  # Erstellt eine NEUE Liste mit demselben Inhalt
 
# Änderungen an der Kopie beeinflussen das Original nicht
copy.append(4)
print(original)  # Output: [1, 2, 3]
print(copy)      # Output: [1, 2, 3, 4]

Jetzt beheben wir unser Einkaufskorb-Beispiel:

python
cart = ["Milk", "Bread"]
backup = cart[:]  # Eine unabhängige Kopie erstellen
 
# Weitere Elemente zum Einkaufskorb hinzufügen
cart.append("Eggs")
cart.append("Butter")
 
# Das Backup bleibt unverändert
print(cart)    # Output: ['Milk', 'Bread', 'Eggs', 'Butter']
print(backup)  # Output: ['Milk', 'Bread']

14.6.3) Kopien mit der Methode copy() erstellen

Listen haben auch eine Methode copy(), die dasselbe tut wie [:]:

python
original = [10, 20, 30]
copy = original.copy()
 
copy.append(40)
print(original)  # Output: [10, 20, 30]
print(copy)      # Output: [10, 20, 30, 40]

Sowohl [:] als auch copy() erstellen flache Kopien (shallow copies), worüber wir als Nächstes sprechen.

14.6.4) Die Einschränkung flacher Kopien

Sowohl [:] als auch copy() erstellen flache Kopien (shallow copies). Das bedeutet, sie kopieren die Listenstruktur, aber wenn die Liste andere veränderbare Objekte enthält (wie andere Listen), werden diese inneren Objekte weiterhin gemeinsam genutzt:

python
# Eine Liste, die Listen enthält
original = [[1, 2], [3, 4], [5, 6]]
copy = original[:]
 
# Das Ändern der äußeren Listenstruktur ist unabhängig
copy.append([7, 8])
print(original)  # Output: [[1, 2], [3, 4], [5, 6]]
print(copy)      # Output: [[1, 2], [3, 4], [5, 6], [7, 8]]
 
# Aber das Ändern einer inneren Liste wirkt sich auf beide aus!
copy[0].append(99)
print(original)  # Output: [[1, 2, 99], [3, 4], [5, 6]]
print(copy)      # Output: [[1, 2, 99], [3, 4], [5, 6], [7, 8]]

Warum passiert das? Weil die flache Kopie eine neue äußere Liste erstellt, die inneren Listen aber weiterhin gemeinsame Referenzen sind:

original outer list

Inner list: ⦗1, 2, 99⦘

Inner list: ⦗3, 4⦘

Inner list: ⦗5, 6⦘

copy outer list

Inner list: ⦗7, 8⦘

Für verschachtelte Strukturen benötigen Sie eine tiefe Kopie(deep copy), die wir kennenlernen werden, wenn wir in späteren Kapiteln das Modul copy erkunden. Für den Moment sollten Sie wissen, dass flache Kopien perfekt für Listen aus unveränderlichen Elementen (Zahlen, Strings, Tupel) funktionieren, aber bei verschachtelten veränderbaren Strukturen Vorsicht erfordern.

14.6.5) Wann gemeinsame Referenzen nützlich sind

Manchmal möchten Sie, dass mehrere Variablen auf dieselbe Liste verweisen. Das ist nützlich, wenn Sie eine Liste von verschiedenen Teilen Ihres Codes aus verändern müssen:

python
# Eine Funktion, die eine Liste direkt verändert
def add_bonus_points(scores, bonus):
    for i in range(len(scores)):
        scores[i] = scores[i] + bonus
 
# Die ursprüngliche Liste wird verändert
student_scores = [85, 92, 78]
add_bonus_points(student_scores, 5)
print(student_scores)  # Output: [90, 97, 83]

Das funktioniert, weil die Funktion eine Referenz auf die ursprüngliche Liste erhält, nicht eine Kopie. Wir werden das genauer untersuchen, wenn wir Funktionen im Detail in Teil V studieren.

14.7) enumerate() beim Durchlaufen von Listen verwenden

14.7.1) Die Notwendigkeit von Index und Wert

Manchmal benötigen Sie beim Iterieren über eine Liste sowohl den Index als auch den Wert. Ein Ansatz ist die Verwendung von range(len(list)):

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
for i in range(len(students)):
    print(f"Student {i}: {students[i]}")
 
# Output:
# Student 0: Alice
# Student 1: Bob
# Student 2: Charlie
# Student 3: Diana

Das funktioniert, ist aber nicht besonders elegant. Sie müssen students[i] verwenden, um auf jeden Wert zuzugreifen, was weniger lesbar ist als das direkte Iterieren über die Werte.

14.7.2) enumerate() für übersichtlicheren Code verwenden

Die Funktion enumerate() bietet eine bessere Lösung. Sie gibt sowohl den Index als auch den Wert für jedes Element zurück:

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
for index, student in enumerate(students):
    print(f"Student {index}: {student}")
 
# Output:
# Student 0: Alice
# Student 1: Bob
# Student 2: Charlie
# Student 3: Diana

Die Syntax for index, value in enumerate(list) entpackt jedes Paar, das enumerate() erzeugt. Das ist deutlich lesbarer als die Verwendung von range(len()).

14.7.3) enumerate() mit einer anderen Startzahl beginnen

Standardmäßig beginnt enumerate() bei 0 zu zählen. Sie können mit dem Parameter start eine andere Startzahl angeben:

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Bei 1 statt 0 zu zählen beginnen
for position, student in enumerate(students, start=1):
    print(f"Position {position}: {student}")
 
# Output:
# Position 1: Alice
# Position 2: Bob
# Position 3: Charlie
# Position 4: Diana

Das ist nützlich, wenn Sie eine menschenfreundliche Nummerierung (beginnend bei 1) statt einer programmiererfreundlichen Indizierung (beginnend bei 0) anzeigen möchten.

Praktische Beispiele mit enumerate()

Hier ist ein praktisches Beispiel, das ein nummeriertes Menü anzeigt:

python
menu_items = ["New Game", "Load Game", "Settings", "Quit"]
 
print("Main Menu:")
for number, item in enumerate(menu_items, start=1):
    print(f"{number}. {item}")
 
# Output:
# Main Menu:
# 1. New Game
# 2. Load Game
# 3. Settings
# 4. Quit

14.7.4) Listen mit enumerate() verändern

Sie können enumerate() verwenden, wenn Sie Listenelemente basierend auf ihrer Position verändern müssen:

python
# Einen positionsbasierten Bonus zu Punktzahlen hinzufügen
scores = [85, 92, 78, 95, 88]
 
for index, score in enumerate(scores):
    # Der erste Schüler erhält 5 Bonuspunkte, der zweite 4, usw.
    bonus = 5 - index
    if bonus > 0:
        scores[index] = score + bonus
 
print(scores)  # Output: [90, 96, 81, 97, 89]

14.8) Häufige Listenmuster: Suchen, Filtern und Daten aggregieren

14.8.1) Nach Elementen in Listen suchen

Eine der häufigsten Aufgaben ist zu prüfen, ob eine Liste ein bestimmtes Element enthält. Der Operator in (den wir in Kapitel 7 gelernt haben) macht das einfach:

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Prüfen, ob ein Schüler in der Liste ist
if "Charlie" in students:
    print("Charlie is enrolled")  # Output: Charlie is enrolled
 
if "Eve" not in students:
    print("Eve is not enrolled")  # Output: Eve is not enrolled

Um die Position eines Elements zu finden, verwenden Sie die Methode index() (in Abschnitt 14.3.9 behandelt), aber denken Sie daran, zuerst zu prüfen, ob das Element existiert:

python
scores = [85, 92, 78, 95, 88]
target_score = 95
 
if target_score in scores:
    position = scores.index(target_score)
    print(f"Score {target_score} found at index {position}")
    # Output: Score 95 found at index 3
else:
    print(f"Score {target_score} not found")

14.8.2) Die maximalen und minimalen Werte finden

Pythons eingebaute Funktionen max() und min() funktionieren mit Listen:

python
scores = [85, 92, 78, 95, 88, 91, 76]
 
highest_score = max(scores)
lowest_score = min(scores)
 
print(f"Highest score: {highest_score}")  # Output: Highest score: 95
print(f"Lowest score: {lowest_score}")    # Output: Lowest score: 76

14.8.3) Aggregate berechnen: Summe, Durchschnitt und Anzahl

Das Berechnen von Summen und Durchschnittswerten ist eine grundlegende Listenoperation:

python
scores = [85, 92, 78, 95, 88, 91, 76, 89]
 
# Summe und Durchschnitt berechnen
total = sum(scores)
count = len(scores)
average = total / count
 
print(f"Total: {total}")        # Output: Total: 694
print(f"Count: {count}")        # Output: Count: 8
print(f"Average: {average:.2f}")  # Output: Average: 86.75

Hier ist ein praktisches Beispiel, das die Gesamtsumme eines Einkaufskorbs berechnet:

python
cart_items = ["Milk", "Bread", "Eggs", "Butter", "Cheese"]
prices = [3.99, 2.49, 4.99, 5.49, 6.99]
 
# Gesamtkosten berechnen
total_cost = sum(prices)
item_count = len(cart_items)
 
print(f"Items in cart: {item_count}")
print(f"Total cost: ${total_cost:.2f}")
 
# Output:
# Items in cart: 5
# Total cost: $23.95

14.9) Veränderbarkeit von Listen und Truthiness in Bedingungen

14.9.1) Veränderbarkeit von Listen in der Praxis verstehen

Wir haben in diesem Kapitel gesehen, dass Listen veränderbar (mutable) sind – sie können nach der Erstellung geändert werden. Diese Veränderbarkeit macht Listen so mächtig für das Speichern und Manipulieren von Datensammlungen. Festigen wir unser Verständnis mit einem umfassenden Beispiel:

python
# Mit einer leeren Aufgabenliste beginnen
tasks = []
print(f"Initial tasks: {tasks}")  # Output: Initial tasks: []
 
# Aufgaben hinzufügen
tasks.append("Write code")
tasks.append("Test code")
tasks.append("Deploy code")
print(f"After adding: {tasks}")
# Output: After adding: ['Write code', 'Test code', 'Deploy code']
 
# Eine dringende Aufgabe am Anfang einfügen
tasks.insert(0, "Review requirements")
print(f"After inserting: {tasks}")
# Output: After inserting: ['Review requirements', 'Write code', 'Test code', 'Deploy code']
 
# Die erste Aufgabe abschließen und entfernen
completed = tasks.pop(0)
print(f"Completed: {completed}")  # Output: Completed: Review requirements
print(f"Remaining: {tasks}")
# Output: Remaining: ['Write code', 'Test code', 'Deploy code']
 
# Eine Aufgabe ändern
tasks[1] = "Test code thoroughly"
print(f"After modifying: {tasks}")
# Output: After modifying: ['Write code', 'Test code thoroughly', 'Deploy code']

14.9.2) Veränderbarkeit vs. Unveränderlichkeit: Listen vs. Strings

Es ist wichtig, den Unterschied zwischen veränderbaren Listen und unveränderlichen Strings zu verstehen. Bei Strings erzeugen Operationen neue Strings, statt das Original zu verändern:

python
# Strings sind unveränderlich
text = "hello"
text.upper()  # Erstellt einen neuen String, verändert das Original nicht
print(text)  # Output: hello (unchanged)
 
# Um einen String zu "ändern", müssen Sie neu zuweisen
text = text.upper()
print(text)  # Output: HELLO
 
# Listen sind veränderbar
numbers = [1, 2, 3]
numbers.append(4)  # Verändert die Liste direkt
print(numbers)  # Output: [1, 2, 3, 4] (changed)

Dieser Unterschied beeinflusst, wie Sie mit diesen Typen arbeiten:

python
# String-Operationen erfordern eine Neuzuweisung
name = "alice"
name = name.capitalize()  # Muss neu zugewiesen werden, damit die Änderung sichtbar wird
print(name)  # Output: Alice
 
# Listen-Operationen verändern direkt
scores = [85, 92, 78]
scores.append(95)  # Keine Neuzuweisung nötig
print(scores)  # Output: [85, 92, 78, 95]

14.9.3) Listen in booleschen Kontexten verwenden

Listen haben Truthiness (truthiness): Eine leere Liste gilt als False, und jede nicht-leere Liste gilt als True. Das ist in bedingten Anweisungen nützlich:

python
# Leere Liste ist falsy
empty_cart = []
if empty_cart:
    print("Cart has items")
else:
    print("Cart is empty")  # Output: Cart is empty
 
# Nicht-leere Liste ist truthy
cart_with_items = ["Milk", "Bread"]
if cart_with_items:
    print("Cart has items")  # Output: Cart has items

Dieses Muster wird häufig verwendet, um zu prüfen, ob eine Liste Elemente hat, bevor man sie verarbeitet:

python
students = ["Alice", "Bob", "Charlie"]
 
if students:
    print(f"We have {len(students)} students")
    for student in students:
        print(f"  - {student}")
else:
    print("No students enrolled")
 
# Output:
# We have 3 students
#   - Alice
#   - Bob
#   - Charlie

14.9.4) Praktisches Muster: Verarbeiten bis leer

Die Truthiness von Listen ermöglicht ein nützliches Muster, um Elemente zu verarbeiten, bis eine Liste leer ist:

python
# Aufgaben verarbeiten, bis keine mehr übrig sind
tasks = ["Task 1", "Task 2", "Task 3"]
 
while tasks:  # Fortfahren, solange die Liste nicht leer ist
    current_task = tasks.pop(0)
    print(f"Processing: {current_task}")
 
print("All tasks completed!")
 
# Output:
# Processing: Task 1
# Processing: Task 2
# Processing: Task 3
# All tasks completed!

14.9.5) Auf leere Listen prüfen: Explizit vs. implizit

Es gibt zwei Möglichkeiten zu prüfen, ob eine Liste leer ist:

python
items = []
 
# Implizite Prüfung (Pythonic)
if not items:
    print("List is empty")  # Output: List is empty
 
# Explizite Prüfung (auch gültig)
if len(items) == 0:
    print("List is empty")  # Output: List is empty

Die implizite Prüfung (if not items:) wird in Python im Allgemeinen bevorzugt, weil sie knapper ist und mit jedem Collection-Typ funktioniert. Allerdings sind beide Ansätze korrekt, und Sie werden beide in echtem Code sehen.

14.9.6) Veränderbarkeit und Funktionsverhalten

Wenn Sie eine Liste an eine Funktion übergeben (was wir in Teil V im Detail untersuchen werden), erhält die Funktion eine Referenz auf dasselbe Listenobjekt. Das bedeutet, die Funktion kann die ursprüngliche Liste verändern:

python
def add_item(shopping_list, item):
    shopping_list.append(item)
    print(f"Added {item}")
 
# Die ursprüngliche Liste wird verändert
cart = ["Milk", "Bread"]
print(f"Before: {cart}")  # Output: Before: ['Milk', 'Bread']
 
add_item(cart, "Eggs")     # Output: Added Eggs
print(f"After: {cart}")    # Output: After: ['Milk', 'Bread', 'Eggs']

Dieses Verhalten unterscheidet sich von unveränderlichen Typen wie Strings und Zahlen, bei denen der ursprüngliche Wert nicht von einer Funktion geändert werden kann. Dieses Verständnis ist entscheidend, um korrekte Programme zu schreiben.


Listen sind eine der grundlegendsten und vielseitigsten Datenstrukturen in Python. Sie bieten eine geordnete, veränderbare Sammlung, die nach Bedarf wachsen und schrumpfen kann, wodurch sie perfekt zum Speichern und Verarbeiten von Sequenzen zusammengehöriger Daten geeignet sind. Sie haben gelernt, wie Sie Listen erstellen, über Indizierung und Slicing auf ihre Elemente zugreifen, sie mit verschiedenen Methoden verändern, effizient über sie iterieren und ihre veränderbare Natur verstehen.

Die Muster, die wir erkundet haben – Suchen, Filtern, Aggregieren und Transformieren von Daten – bilden die Grundlage für die Arbeit mit Sammlungen in Python. Während Sie weiter lernen, werden Sie noch leistungsfähigere Möglichkeiten entdecken, mit Listen zu arbeiten, darunter List Comprehensions (Kapitel 35) und fortgeschrittene Iterationstechniken (Kapitel 36–37). Aber die Grundlagen, die Sie in diesem Kapitel gemeistert haben, werden Ihnen auf Ihrer gesamten Python-Programmierreise gute Dienste leisten.


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