Eine list ist eine veränderbare Sammlung von Elementen in Sequenz.
Wie die meisten Sammlungen (siehe die eingebauten tuple, dict und set) können Listen Referenzen auf beliebige (oder mehrere) Datentypen enthalten, auch auf andere Listen.
In Python gelten sie als Sequenz und können vollständig oder teilweise über die Slice-Notation kopiert werden.
Wie bei jeder Sequenz kannst du Elemente in lists über eine 0-based index-Zahl von links oder eine -1-based index-Zahl von rechts ansprechen.
Listen unterstützen sowohl gemeinsame als auch veränderbare Sequenzoperationen wie min(<list>)/max(<list>), <list>.index(), <list>.append() und <list>.reverse().
Elemente kannst du mit dem Konstrukt for item in <list> durchlaufen, und mit for index, item in enumerate(<list>), wenn du sowohl das Element als auch seinen Index brauchst.
Python bietet viele nützliche Methoden für die Arbeit mit Listen.
Da Listen veränderbar sind, verändern Listenmethoden das ursprüngliche Listenobjekt, das du an die Methode übergibst.
Wenn du die ursprüngliche list nicht verändern willst, musst du (mindestens) eine shallow copy davon anlegen, über einen slice oder <list>.copy().
Elemente kannst du mit <list>.append(<item>) am Ende einer bestehenden Liste hinzufügen:
>>> numbers = [1, 2, 3]
>>> numbers.append(9)
>>> numbers
[1, 2, 3, 9]
Anstatt das Element anzuhängen, fügt <list>.insert(<index>, <item>) es an einem bestimmten Index in die Liste ein.
<index> ist der Index des Elements, vor dem das neue Element erscheinen soll.
<item> ist das Element, das eingefügt werden soll.
Hinweis: Wenn <index> 0 ist, wird das Element am Anfang der Liste eingefügt.
Ist <index> größer als der letzte Index der Liste, wird das Element an der letzten Position eingefügt, was <list>.append(<item>) entspricht.
>>> numbers = [1, 2, 3]
>>> numbers.insert(0, -2)
>>> numbers
[-2, 1, 2, 3]
>>> numbers.insert(1, 0)
>>> numbers
[-2, 0, 1, 2, 3]
Ein iterable kannst du mit einer bestehenden Liste zusammenführen (die beiden werden konkateniert), indem du <list>.extend(<iterable>) verwendest.
<list>.extend(<iterable>) entpackt das übergebene Iterable und hängt seine Elemente in derselben Reihenfolge an das Ende der Zielliste an.
Würdest du in diesem Fall <list>.append(<item>) verwenden, würde das gesamte Iterable als ein einzelnes Element hinzugefügt.
>>> numbers = [1, 2, 3]
>>> other_numbers = [5, 6, 7]
>>> numbers.extend(other_numbers)
>>> numbers
[1, 2, 3, 5, 6, 7]
>>> numbers.extend([8, 9])
>>> numbers
[1, 2, 3, 5, 6, 7, 8, 9]
Mit <list>.remove(<item>) kannst du ein Element aus der Liste entfernen.
<list>.remove(<item>) wirft einen ValueError, wenn das Element nicht in der Liste vorkommt.
>>> numbers = [1, 2, 3]
>>> numbers.remove(2)
>>> numbers
[1, 3]
# Trying to remove a value that is not in the list throws a ValueError.
>>> numbers.remove(0)
ValueError: list.remove(x): x not in list
Alternativ entfernt die Methode <list>.pop(<index>) ein Element und gibt es dir mit return zur weiteren Verwendung zurück.
<list>.pop(<index>) nimmt einen optionalen Parameter: den index des Elements, das entfernt und zurückgegeben werden soll.
Wenn du das optionale <index>-Argument nicht angibst, wird das letzte Element der Liste entfernt und zurückgegeben.
Ist <index> größer als der letzte Index der Liste, wird ein IndexError geworfen.
>>> numbers = [1, 2, 3]
>>> numbers.pop(0)
1
>>> numbers
[2, 3]
>>> numbers.pop()
3
>>> numbers
[2]
# This will throw an error because there is only index 0.
>>> numbers.pop(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop index out of range
Alle Elemente kannst du mit <list>.clear() aus einer list entfernen. Die Methode nimmt keine Parameter.
>>> numbers = [1, 2, 3]
>>> numbers.clear()
>>> numbers
[]
Die Reihenfolge der Listenelemente kannst du mit <list>.reverse() an Ort und Stelle umkehren. Das verändert die ursprüngliche Liste.
>>> numbers = [1, 2, 3]
>>> numbers.reverse()
>>> numbers
[3, 2, 1]
Eine Liste kannst du mit Hilfe von <list>.sort() an Ort und Stelle neu ordnen.
Die standardmäßige Sortierreihenfolge ist aufsteigend von links.
Die Python-Dokumentation bietet weitere Tipps und Techniken zum Sortieren.
Von 2002 bis 2022 hat Python intern einen Algorithmus namens Timsort verwendet, um Listen zu sortieren, ist aber ab Python 3.11 auf Powersort umgestiegen.
Mehr Details und die Diskussion des Python-Kernteams zu dieser Änderung findest du im GitHub-Issue 78742.
Technische Details zum Algorithmus findest du im Paper von J. Ian Munro und Sebastian Wild: Nearly-Optimal Mergesorts: Fast, Practical Sorting Methods That Optimally Adapt to Existing Runs
>>> names = ["Tony", "Natasha", "Thor", "Bruce"]
# The default sort order is *ascending*.
>>> names.sort()
>>> names
["Bruce", "Natasha", "Thor", "Tony"]
Um eine Liste absteigend zu sortieren, übergibst du der Methode ein reverse=True-Argument:
>>> names = ["Tony", "Natasha", "Thor", "Bruce"]
>>> names.sort(reverse=True)
>>> names
["Tony", "Thor", "Natasha", "Bruce"]
Wenn du die ursprüngliche list nicht verändern willst, kannst du die eingebauten Funktionen sorted() und reversed() verwenden.
sorted(<list>) gibt eine sortierte Kopie zurück und nimmt dieselben Parameter wie <list>.sort().
reversed(<list>) gibt einen Iterator zurück, der die Elemente der Liste in umgekehrter Reihenfolge liefert.
Iterators werden in einer anderen Übung ausführlich behandelt.
Die Anzahl der Vorkommen eines Elements in einer Liste kannst du mit <list>.count(<item>) ermitteln.
Die Methode gibt zurück, wie oft <item> insgesamt als Element in der Liste vorkommt.
>>> items = [1, 4, 7, 8, 2, 9, 2, 1, 1, 0, 4, 3]
>>> items.count(1)
3
<list>.index(<item>) gibt die Indexnummer des ersten Vorkommens eines übergebenen Elements zurück.
Gibt es kein Vorkommen, wird ein ValueError ausgelöst.
Die Indexierung ist 0-based von links, das heißt, die Position des ersten Elements ist der Index 0.
Auch die Indexierung von rechts wird unterstützt, beginnend mit dem Index -1.
>>> items = [7, 4, 1, 0, 2, 5]
>>> items.index(4)
1
>>> items.index(10)
ValueError: 10 is not in list
Wenn du start- und end-Indizes angibst, wird nur in einem bestimmten Abschnitt der Liste gesucht:
>>> names = ["Tina", "Leo", "Thomas", "Tina", "Emily", "Justin"]
>>> names.index("Tina")
0
>>> names.index("Tina", 2, 5)
3
Wenn du die genaue Position eines Elements nicht brauchst, ist der eingebaute in-Operator effizienter, um zu prüfen, ob es enthalten ist.
>>> names = ["Tina", "Leo", "Thomas", "Tina", "Emily", "Justin"]
>>> "Thomas" in names
True
Denk daran, dass Variablen in Python Namen sind, die auf dahinterliegende Objekte zeigen.
Namen können im Laufe eines Programms an verschiedene Objekte gebunden und wieder neu gebunden werden.
Wenn du ein list-Objekt einem neuen Variablen namen zuweist, wird das Objekt und keines der referenzierten Daten kopiert.
Der neue und der alte Name zeigen beide auf dasselbe list-Objekt.
Außerdem sind Listen ein Container-Typ. Um Platz zu sparen, halten Container nur Referenzen auf ihre Elemente, nicht die Elemente selbst.
Diese „Optimierung“ kann für Unvorsichtige unerwartete Folgen haben.
<list>.copy() erstellt ein neues list-Objekt, legt aber keine neuen Objekte für die referenzierten Listen- elemente an. Die Kopie ist „flach“.
Eine shallow copy reicht meist aus, wenn du Elemente aus einem der list-Objekte hinzufügen oder entfernen willst, ohne das andere zu verändern.
Wenn aber die Möglichkeit besteht, dass die darunterliegenden Elemente einer list versehentlich verändert werden (und damit alle zugehörigen flachen Kopien), solltest du copy.deepcopy() aus dem copy-Modul verwenden, um eine vollständige oder „tiefe“ Kopie aller Referenzen und Objekte zu erstellen.
Eine ausführliche Erklärung zu Namen, Werten, Listen und dem Verhalten verschachtelter Listen findest du in diesem großartigen Blogbeitrag von Ned Batchelder: Names and values: making a game board. Shallow vs Deep Copying of Python Objects bietet ebenfalls einen guten Überblick über Kopier-Überlegungen.