In Python sind Zeichenfolgen (str) unveränderliche Objekte, das heißt, nach ihrer Erstellung kann ihr Inhalt nicht geändert werden. Jede Operation, die eine Zeichenfolge modifiziert (z. B. Verkettung oder Ersetzung von Zeichen), erzeugt ein neues Zeichenfolgenobjekt. Dies gewährleistet Sicherheit und Vorhersehbarkeit, da man sich keine Sorgen machen muss, dass jemand die Zeichenfolge an anderer Stelle im Code heimlich ändert.
s = 'Hello' s2 = s.replace('H', 'J') # s bleibt 'Hello', und s2 wird 'Jello'
Im Gegensatz zu Zeichenfolgen sind Listen in Python veränderliche Objekte. Ihr Inhalt kann durch Indizierung oder Methoden vor Ort geändert werden, was manchmal zu unerwarteten Effekten führen kann, wenn dieselbe Liste an verschiedenen Stellen verwendet wird.
In Bezug auf die Leistung: Wenn man häufig große Zeichenfolgen ändern muss (z. B. in einer Schleife), kann die Mechanik der Unveränderlichkeit zu übermäßiger Speicherzuweisung und langsamer Ausführung des Codes führen. In solchen Fällen wird empfohlen, eine Liste zu verwenden, um Fragmente der Zeichenfolge zu sammeln, und sie dann mit ''.join() zu verbinden.
Beispiel:
# Schlecht (langsam für große Datenmengen): s = '' for word in words: s += word # Bei jedem Schritt wird eine neue Zeichenfolge erstellt # Gut: parts = [] for word in words: parts.append(word) s = ''.join(parts)
Frage: Warum ist der folgende Code "s += 'abc'" schneller als "s = s + 'abc'" für Zeichenfolgen?
Antwort: Solche Fragen werden gestellt, um zu prüfen, ob die Person versteht, dass beide Operationen für Zeichenfolgen tatsächlich gleichwertig sind (s += 'abc' erstellt ein neues Objekt, genau wie s = s + 'abc') — so funktioniert das Verhalten von Typen in Python. Für Listen ist das Verhalten anders, denn list += [...] verändert das Objekt, während list = list + [...] ein neues erstellt. Bei Zeichenfolgen ist es immer eine neue Zeichenfolge.
s = 'hi' s += 'abc' # Neues Objekt, die ursprüngliche Zeichenfolge wird nicht geändert def compare(s): a = s a += 'abc' # id(a) != id(s) <-- verschiedene Objekte im Speicher
Geschichte
In einem Projekt, in dem die Verarbeitung großer Logs (Analyse von Zeichenfolgen mit Hunderten von Megabyte Länge) erforderlich war, verwendete der Entwickler naive Zeichenfolgenverkettung in einer Schleife. Das Ergebnis waren enorme Leistungsabfälle und ein schneller Anstieg des Speicherverbrauchs. Nach der Optimierung durch eine Liste und join() reduzierte sich die Ausführungszeit um das 20-Fache.
Geschichte
In einem Projekt erwartete der Programmierer, beim Versuch, ein Zeichen in einer Zeichenfolge nach Index zu "korrigieren", eine Änderung der ursprünglichen Zeichenfolge. Es trat ein Fehler auf: TypeError: 'str' object does not support item assignment. Nachdem er mehrere Stunden damit verbracht hatte, musste der Debugger eine neue Zeichenfolge mit Hilfe von Slices erstellen und das benötigte Zeichen ersetzen.
Geschichte
Beim Übergeben von Zeichenfolgen an eine Funktion zur "Ergänzung" (z. B. um ein Suffix zu jedem Element aus einer Liste hinzuzufügen), erwartete einer der Entwickler, dass die Zeichenfolge "vor Ort" geändert wird. Das Ergebnis war, dass die Funktion None zurückgab (aufgrund fehlenden returns), und alle Zeichenfolgen blieben unverändert.