In Python sind Listen (list) veränderbare Strukturen, während Tupel (tuple) unveränderlich sind.
Beispiel, das die Änderung von list und tuple veranschaulicht:
lst = [1, 2, 3] lst.append(4) # OK lst[1] = 20 # OK tup = (1, 2, 3) tup[1] = 20 # TypeError
Leistung:
Frage: Warum werden Operationen zum Hinzufügen von Elementen zu einer Liste normalerweise schnell (O(1)) ausgeführt, obwohl dies aus der Sicht eines Arrays zu einer Neuzuordnung des Speichers führen sollte?
Antwort:
Python implementiert dynamische Arrays mit "Überreservierung von Speicher" sofort für mehrere Elemente. Daher benötigt append normalerweise O(1), und die Neuzuordnung des Speichers erfolgt nur, wenn der Reserveblock tatsächlich erschöpft ist.
Beispiel:
import sys lst = [] for i in range(10): lst.append(i) print(len(lst), sys.getsizeof(lst)) # Speichergröße wächst nicht strikt linear
Geschichte
In einem Projekt wurden für die Schlüssel eines Dictionaries list verwendet. Der Entwickler wusste nicht, dass Listen nicht gehasht werden (Veränderlichkeit), was zu einem Fehler "TypeError: unhashable type: 'list'" führte.
Der Entwickler erstellte häufig lange Listen, indem er sie über + konkateniert. Dies führte zu zusätzlichen Kopien des Arrays und hohen Speicher- und Zeitkosten. Effektiver war es, append in einer Schleife oder Generatoren zu verwenden.
Im Loggingsystem wurden für die Speicherung von Zeitstempeln Tupel gewählt, in der Annahme, dass sie aufgrund von Unveränderlichkeit schneller wären. Es stellte sich jedoch regelmäßig die Notwendigkeit zur Modifikation ein, was erfordete, ständig neue Tupel (copy-on-write) zu erstellen, was die Leistung im Vergleich zur Verwendung von Listen verlangsamte.