Zum Inhalt
wannacode

Listen: append, remove und sort

Kurz gesagt: Eine Liste ist eine Collection, die wächst und schrumpft: append hängt hinten an, remove nimmt ein Element heraus, ohne eine Lücke zu lassen, und sort bringt sie in Reihenfolge.

Problem

Der Warenkorb ist voll

Du schreibst den Warenkorb eines Onlineshops und hältst die Artikel in einer Liste, wie in der Lektion über Arrays: jeder Artikel an seinem Index. Aber über das Ende hinaus kannst du nicht schreiben: cart[3] = "Butter" bricht das Programm mit IndexError: list assignment index out of range ab. Für einen vierten Artikel legst du also eine neue, längere Liste an. Und nimmt der Kunde einen Artikel heraus, bleibt eine Lücke:

cart = ["Brot", "Milch", "Kaffee"]
# Ein vierter Artikel: cart[3] = "Butter" bricht mit IndexError ab,
# also legen wir eine neue, längere Liste an.
cart = cart + ["Butter"]
# Der Kunde nimmt die Milch heraus.
cart[1] = None
for item in cart:
print(item)
Ausgabe
Brot
None
Kaffee
Butter
Jetzt muss jede Schleife über den Warenkorb None überspringen. Und die Zahl der Artikel ist nicht mehr len(cart).

Das ist viel Code für etwas, das jeder Shop ständig macht.

Die Idee

append und remove: Die Liste kümmert sich selbst

Die Liste hat Methoden, die das für dich erledigen. Innen hält sie die Elemente immer noch in einem Array, aber das Kopieren und Verschieben macht sie selbst. Eine Collection, die so wächst und schrumpft, heißt Liste:

cart = []
cart.append("Brot")
cart.append("Milch")
cart.append("Kaffee")
cart.append("Butter")
cart.remove("Milch")
print(cart)
print("Artikel:", len(cart))
Ausgabe
['Brot', 'Kaffee', 'Butter']
Artikel: 3
  • append hängt hinten an.
  • remove entfernt das Element mit diesem Wert und schließt die Lücke: „Kaffee“ rückt auf den Platz von „Milch“. Steht der Wert mehrmals darin, entfernt es den ersten.
  • len(cart) ist die Zahl der Elemente gerade jetzt.
  • print gibt die ganze Liste in eckigen Klammern aus, den Text in Anführungszeichen.

So sieht es in der Liste aus. Wie viele Plätze das Array hat, wählst nicht du. Das macht CPython, das Programm, das deinen Code ausführt. Eine Liste mit 4 Artikeln, die im Code steht, hat genau 4 Plätze, also ist das Array beim fünften voll:

cart = ["Brot", "Milch", "Kaffee", "Butter"]
cart.append("Käse")
cart.remove("Milch")
print(cart)
print("Artikel:", len(cart))
Schritt für Schritt, in Worten
  1. cart zeigt auf ein Listenobjekt. Darin liegen ein Zähler ob_size und ein Array ob_item mit 4 Plätzen.
  2. Die Artikel aus dem Code füllen die Plätze nacheinander. Das Array ist voll: 4 von 4.
  3. Es ist kein Platz mehr. append reserviert ein Array mit 8 Plätzen, und die Elemente kommen hinein.
  4. ob_item zeigt jetzt auf das neue Array. „Käse“ kommt auf den ersten freien Platz.
  5. remove entfernt „Milch“, und alles danach rückt einen Platz nach links. Es bleibt keine Lücke.
  6. Von außen siehst du nur eine Liste mit vier Artikeln. Wie viele Plätze sie innen hat, entscheidet CPython: Die Sprache verspricht es nicht.

Die Idee

Was in eine Liste passt

Eine Liste fragt nicht, was du hineinlegst. Text und eine Zahl können nebeneinander stehen:

cart = []
cart.append("Brot")
cart.append(5)
print(cart)
Ausgabe
['Brot', 5]

Das sieht praktisch aus, aber der Fehler zeigt sich später, dort, wo du Text erwartest. Zum Beispiel in einer Schleife, die die Artikel in Großbuchstaben ausgibt:

cart = ["Brot", 5]
for item in cart:
print(item.upper())
Fehler
AttributeError: 'int' object has no attribute 'upper'

„Brot“ wird ausgegeben, und bei der Zahl bricht das Programm ab. Eine Liste hält also eine Art von Dingen: nur Artikel, nur Preise.

Das kannst du mit einem Typhinweis festhalten: list[str] bedeutet „eine Liste mit Text“.

cart: list[str] = []
cart.append("Brot")
cart.append(5)
print(cart)
Ausgabe
['Brot', 5]

Python prüft den Hinweis nicht, während das Programm läuft: Die Zahl kommt trotzdem hinein. Dein Editor und Werkzeuge wie mypy prüfen ihn, bevor du das Programm startest. Diese Lektion hat keine Hinweise, aber in fremdem Code wirst du sie sehen.

Die Idee

Indizes: [i], insert, index, in

Eine Liste hat Indizes wie ein Array, von 0 bis len(tasks) - 1, und du schreibst sie mit denselben [ ]:

tasks = ["Rechnung März", "Bank anrufen", "Lagerbericht"]
print(tasks[0])
tasks[1] = "Termin bei der Bank"
tasks.insert(0, "Kaffee mit dem Team")
print(tasks)
print(tasks.index("Lagerbericht"))
print("Bank anrufen" in tasks)
Ausgabe
Rechnung März
['Kaffee mit dem Team', 'Rechnung März', 'Termin bei der Bank', 'Lagerbericht']
3
False
  • tasks[i] liest, und tasks[i] = x ersetzt.
  • insert(i, x) fügt bei Index i ein und schiebt den Rest nach rechts.
  • index(x) sucht und gibt den Index zurück, und x in tasks sagt nur, ob es darin ist.
Genauer, für Neugierige
  • Ein Index außerhalb der Liste bricht das Programm ab. Ein negativer Index zählt von hinten: tasks[-1] ist die letzte Aufgabe. Und index für etwas, das nicht darin ist, bricht das Programm auch ab, also frag zuerst mit in:
tasks = ["Rechnung März", "Bank anrufen", "Lagerbericht"]
try:
print(tasks[3])
except IndexError as e:
print(f"IndexError: {e}")
print(tasks[-1])
try:
tasks.index("Gehälter")
except ValueError as e:
print(f"ValueError: {e}")
Ausgabe
IndexError: list index out of range
Lagerbericht
ValueError: 'Gehälter' is not in list
  • in und index vergleichen mit ==. Darum finden sie gleichen Text, nicht nur dasselbe Objekt.
  • Einfügen und Entfernen vorne sind in einer großen Liste langsam: Jedes Element nach dem Index rückt einen Platz weiter. Bei einer Million Elementen sind das eine Million Verschiebungen.

Probier es aus

Wer ist dran?

Die Liste der Patienten, die beim Arzt warten. Jonas geht hinein, und Anna hat einen Termin, darum bekommt sie den zweiten Platz.

Was gibt das Programm aus?

waiting = ["Jonas", "Maria", "Peter"]
waiting.pop(0)
waiting.insert(1, "Anna")
print(waiting, len(waiting))
Antwort

Die Idee

Die Elemente durchlaufen

Eine Liste durchläufst du mit for, wenn du nur die Elemente brauchst. Brauchst du auch die Nummer, gibt es enumerate:

cart = ["Brot", "Kaffee", "Butter"]
for item in cart:
print(f"- {item}")
for number, item in enumerate(cart, start=1):
print(f"{number}. {item}")
Ausgabe
- Brot
- Kaffee
- Butter
1. Brot
2. Kaffee
3. Butter

enumerate(cart, start=1) gibt bei jedem Schritt zwei Werte: die Nummer und das Element. Ohne start=1 beginnen die Nummern bei 0, wie die Indizes. Du kannst auch einen Index nehmen, wie in der Lektion über Arrays, mit for i in range(len(cart)), aber enumerate ist in Python der übliche Weg.

Genauer, für Neugierige
  • Entferne keine Elemente aus einer Liste, während du sie mit for durchläufst. Das Programm bricht nicht ab, aber es überspringt Elemente:
cart = ["Brot", "Brot", "Milch"]
for item in cart:
if item == "Brot":
cart.remove(item)
print(cart)
Ausgabe
['Brot', 'Milch']

Das zweite „Brot“ ist geblieben. remove hat alles nach links verschoben, und die Schleife ging beim nächsten Index weiter und hat es nie gesehen. Es gibt keinen Fehler, darum ist so ein Versäumnis schwer zu finden.

  • Wenn du entfernen musst, durchläufst du mit einem Index von hinten nach vorne. So verschiebt das Entfernen nicht die Elemente, die du noch nicht geprüft hast:
cart = ["Brot", "Brot", "Milch"]
for i in range(len(cart) - 1, -1, -1):
if cart[i] == "Brot":
cart.pop(i)
print(cart)
Ausgabe
['Milch']
Im Modul „Modernes Python“ siehst du einen kürzeren Weg, der eine neue Liste nur mit den gewünschten Elementen erzeugt.

Die Idee

Zahlen in einer Liste

Eine Liste mit Noten ist wie eine Liste mit Text. Die Zahl liegt so in der Liste, wie sie ist:

scores = [85, 64, 91]
total = 0
for score in scores:
total += score
print("Durchschnitt:", total / len(scores))
print("Durchschnitt:", sum(scores) / len(scores))
Ausgabe
Durchschnitt: 80.0
Durchschnitt: 80.0
  • / gibt eine Kommazahl, darum ist der Durchschnitt 80.0, nicht 80.
  • sum addiert alle Zahlen der Liste. Beide Zeilen berechnen dasselbe.
Genauer, für Neugierige
  • In Python ist auch eine Zahl ein Objekt. Für kleine Zahlen, von -5 bis 256, hält Python fertige Objekte bereit, für größere erzeugt es neue. Darum gibt is, das fragt „ist es dasselbe Objekt?“, verschiedene Antworten:
a = int("256")
b = int("256")
c = int("257")
d = int("257")
print(a is b)
print(c is d)
print(c == d)
Ausgabe
True
False
True

Vergleiche Zahlen und Text mit ==: Es fragt, ob die Werte gleich sind. is ist für None: if found is None.

Probier es aus

Finde den Fehler

Ein Theater hält die belegten Plätze in einer Liste. Ein Kunde gibt Platz 2 zurück, und das Programm soll [12, 7, 5] ausgeben. Stattdessen gibt es [12, 2, 5] aus. In welcher Zeile steckt der Fehler?

Wähle die Zeile mit dem Fehler.

Die Idee

Sortieren und eine Liste, die sich nicht ändert

sort() sortiert die Liste an Ort und Stelle: Text alphabetisch, Zahlen nach Größe. sorted(...) rührt nichts an. Es gibt eine neue, sortierte Liste zurück.

cities = ["Hamburg", "Berlin", "Dresden"]
cities.sort()
print(cities)
prices = (30, 5, 12)
print(sorted(prices))
Ausgabe
['Berlin', 'Dresden', 'Hamburg']
[5, 12, 30]

Die Preise stehen in runden Klammern: (30, 5, 12). Das ist ein Tupel, eine Liste, die unveränderlich ist. Du kannst es lesen und durchlaufen, aber darin nichts hinzufügen, entfernen oder sortieren:

days = ("Mo", "Di", "Mi")
days.append("Do")
Fehler
AttributeError: 'tuple' object has no attribute 'append'

Darum werden die Preise oben mit sorted sortiert: Es gibt eine neue Liste zurück, und das Tupel bleibt gleich. Ein Tupel ist für Dinge, die sich nicht ändern: die Wochentage, die zwei Koordinaten eines Punkts.

Genauer, für Neugierige
  • Text wird nach den Codes seiner Zeichen sortiert. Großbuchstaben kommen vor Kleinbuchstaben, darum kommt „Traube“ vor „apfel“:
fruit = ["apfel", "Birne", "banane", "Traube"]
fruit.sort()
print(fruit)
Ausgabe
['Birne', 'Traube', 'apfel', 'banane']
  • Wie du eigene Objekte sortierst, zum Beispiel Produkte nach Preis, siehst du in der Lektion „Klassen in Klassen“.

Übung

Listen in Klassen

Löse die Aufgaben in deinem Editor. Die Liste ist ein Feld der Klasse mit einem _ vorne („von außen nicht anfassen“), und der Code unter den Klassen ruft nur ihre Methoden auf.

1. Ein Bücherregal. Eine Klasse BookShelf mit einer Methode add_book(title), die das Buch ans Ende stellt, und take_book(), die das erste Buch zurückgibt und entfernt (oder None, wenn das Regal leer ist). Füge count() und __str__() hinzu. Füge „Unter dem Joch“, „Tabak“ und „Der eiserne Leuchter“ hinzu, nimm ein Buch und gib den Rest aus.

Ausgabe
Genommen: Unter dem Joch
2 übrig: ['Tabak', 'Der eiserne Leuchter']

2. Ein Ereignisprotokoll. Eine Klasse Event mit einem Datum und einer Beschreibung und eine Klasse EventLog mit den Methoden add_event(date, description) und get_events_between(start, end), die eine Liste der Ereignisse zwischen den beiden Daten zurückgibt, einschließlich. Die Daten sind Text in der Form 2026-03-31. In dieser Form sortiert sich der Text genauso wie die Daten, darum vergleichen <= und >= sie richtig. Füge vier Ereignisse hinzu: 2026-01-15 „Jahresinventur“, 2026-03-31 „Bericht erstes Quartal“, 2026-05-20 „Neuer Kaffeelieferant“, 2026-09-01 „Neues Schuljahr“. Gib die vom 2026-03-01 bis 2026-06-30 aus.

Ausgabe
2026-03-31 Bericht erstes Quartal
2026-05-20 Neuer Kaffeelieferant

3. Ein Notizbuch. Eine Klasse Note mit einem Titel und einem Inhalt und eine Klasse Notebook mit den Methoden add_note, find_note(title) (gibt die Notiz oder None zurück), delete_note(title) (gibt True zurück, wenn es etwas gelöscht hat) und count(). Füge die Notizen „OOP“, „Collections“ und „SQL“ hinzu, finde „Collections“, lösche „OOP“ und prüfe, dass sie weg ist.

Ausgabe
Collections: die Liste wächst von selbst
Gelöscht: OOP
Notizen: 2
Es gibt keine Notiz OOP.

4. Kopfrechnen. Eine Klasse Question mit einem Text und der richtigen Antwort und eine Klasse MathGame mit einer Liste von Fragen, einer Methode add_question und einer Methode start(). start stellt die Fragen nacheinander, liest die Antwort und sagt am Ende, wie viele richtig waren. Die Fragen sind 2 + 2, 3 * 4 und 15 - 9.

Eingabe
4
12
7
Ausgabe
2 + 2 = Richtig!
3 * 4 = Richtig!
15 - 9 = Falsch, die Antwort ist 6.
Ergebnis: 2 von 3

Weitere Aufgaben

  • Keine Wiederholungen. Lies 6 Namen ein und sammle sie in einer Liste, wobei du die überspringst, die schon darin sind. Für die Eingabe Jonas, Maria, Jonas, Anna, Maria, Peter ist die Ausgabe ['Jonas', 'Maria', 'Anna', 'Peter'].
  • Der teuerste Artikel. Eine Liste enthält Preise. Finde den höchsten und seinen Index, ohne max.
  • Die Liste umdrehen. Schreib eine Funktion, die eine neue Liste mit denselben Elementen in umgekehrter Reihenfolge zurückgibt. Ändere das Original nicht.
  • Eine Einkaufsliste. Lies die Befehle add milk, remove milk, list und end und halte die Liste zwischen ihnen. Der Befehl, einen Artikel zu entfernen, der nicht darin ist, sagt „Kein solcher Artikel.“

Test

Teste dich

1. Warum sind append und remove praktischer als das Schreiben per Index?
2. Bisher enthält cart nur Text. Was macht cart.append(5)?
3. seats ist [12, 2, 7, 5]. Was bleibt nach seats.pop(2)?
4. tasks hat 3 Aufgaben. Was macht print(tasks[3])?
5. days = ("Mo", "Di"). Was passiert bei days.append("Mi")?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·