Fehler Python beheben - Dictionary Changed Size During Iteration

Isaac Tony 30 Januar 2023
  1. Erstellen einer flachen Kopie des Dictionaries
  2. Umwandeln von Dictionaryelementen in eine Liste
  3. Anhängen von Schlüsseln an eine leere Liste
Fehler Python beheben - Dictionary Changed Size During Iteration

Dieser Laufzeitfehler tritt auf, wenn wir während der Iteration Einträge in einem Dictionaryobjekt entfernen, ändern oder hinzufügen. Dieser Fehler tritt beim Durchlaufen eines Dictionaries, aber praktisch aller iterierbaren Objekte unabhängig von der verwendeten Programmiersprache auf.

Der folgende Codeausschnitt veranschaulicht, wie dieser Fehler auftritt, wenn ein Dictionary durchlaufen und gleichzeitig Änderungen vorgenommen werden.

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for x in cars.keys():
    cars["color"] = "white"
print(x)

Im obigen Codeblock fügen wir während der Iteration ein neues Element zum ursprünglichen Dictionary hinzu. Dadurch wird ein Laufzeitfehler zurückgegeben, der uns darüber informiert, dass sich die Dictionary größe während der Iteration geändert hat, was bedeutet, dass wir das Dictionary während der gleichzeitigen Iteration nicht ändern können.

Beispielcode:

Traceback (most recent call last):
File "<string>", line 8, in <module>
RuntimeError: dictionary changed size during iteration

Beim Durchführen einer Iteration an einem Objekt werden sowohl das Löschen als auch das Hinzufügen oder Ändern als Änderung betrachtet und können während der Iteration nicht durchgeführt werden. Das folgende Codebeispiel zeigt, dass dieser Fehler auch bestehen bleibt, wenn wir das Dictionary während der Iteration ändern. Daher erhalten wir immer noch denselben Fehler, wenn wir während der Iteration ein vorhandenes Element aus einem Dictionary entfernen.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for x in cars.keys():
    del cars["model"]
print(cars)

Ausgabe:

Traceback (most recent call last):
File "<string>", line 8, in <module>
RuntimeError: dictionary changed size during iteration

In Python 3 wird das Iterieren über ein sich änderndes Objekt als schlechter Code-Schreibstil und als unsicher angesehen. Im Allgemeinen können wir in der Programmierung ein Objekt nicht mutieren, während wir gleichzeitig darüber iterieren; diese Regel erstreckt sich auf iterierbare Elemente wie Listen und sogar Arrays.

Wenn eine Funktion jedoch ein Objekt mutiert, müssen wir sicherstellen, dass die Funktion nur eine Kopie des Originalobjekts mutiert und das Originalobjekt intakt lässt. Dies ist einer der weit verbreiteten Ansätze, um Änderungen an Objekten vorzunehmen, während sie gleichzeitig durchlaufen werden.

Dies ist eine bewährte Vorgehensweise und die beste Methode, um zu vermeiden, dass eine Endlosschleife erstellt wird, die schließlich zu einer Erschöpfung des Speichers führen kann. Um diesen Fehler zu beheben, können mehrere Lösungen verwendet werden, und wir werden jede hier besprechen.

Erstellen einer flachen Kopie des Dictionaries

Python stellt uns das Modul copy() zur Verfügung, mit dem wir eine Kopie eines Objekts ohne Bindung an das Originalobjekt erstellen können. Auf diese Weise können wir die Kopie des Objekts frei ändern und das ursprüngliche Objekt intakt lassen.

Beachten Sie, dass dies nicht mit dem Zuweisungsoperator in Python realisiert werden kann. Durch die Verwendung des Zuweisungsoperators wird keine Kopie des Originalobjekts erstellt, sondern eine Variable, die auf das Originalobjekt verweist.

Daher wirken sich alle am neuen Objekt vorgenommenen Änderungen auch auf das ursprüngliche Objekt aus. Neue Entwickler missbrauchen diesen Operator oft.

Beispielcode:

import copy

cars = {
    "brand": "Tesla",
    "model": "Model S Plaid",
    "year": 2021,
}

# creating a shallow copy
cars_copy = copy.copy(cars)

for x in cars_copy.keys():
    cars["color"] = "black"

print(cars)
print(cars_copy)

Ausgabe:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}
{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021}

Im bereitgestellten Beispielcode haben wir die Funktion copy des Kopiermoduls verwendet, um eine Dictionarykopie zu erstellen, die wir frei iterieren können, ohne das ursprüngliche Dictionary zu beeinträchtigen. Wenn wir Änderungen an einer Dictionarykopie vornehmen, können wir das Dictionary durchlaufen, ohne dass ein Fehler auftritt.

Alternativ können wir den **-Operator verwenden, der oft als die beiden Sternchen-Operatoren bezeichnet wird, um den obigen Code neu zu schreiben, wie unten gezeigt.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

# creating a shallow copy
cars_copy = {**cars}


for x in cars_copy.keys():
    cars["color"] = "black"

print(cars)

Der Operator ** kann Schlüssel-Wert-Paare aus einem Dictionary nehmen und in ein anderes Dictionary übertragen.

Obwohl der Operator häufig verwendet wird, um Schlüsselwortargumente in Python zu übergeben, haben wir den Operator verwendet, um das Dictionary zu entpacken und die Schlüssel-Wert-Paare im obigen Code zu erhalten. Wir erstellen dann eine Kopie des Dictionaries und speichern die entpackten Werte in diesem neuen Dictionary.

Ausgabe:

'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

Das Löschen eines Schlüssel-Wert-Paares aus einem Dictionary ist auch bei der Durchführung einer Iteration keine Ausnahme und sollte daher einem ähnlichen Ansatz folgen. Daher löschen wir mit dem gleichen Verfahren den Schlüssel namens model und seinen Wert Model S Plaid wie unten gezeigt.

Beispielcode:

import copy

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021, "color": "black"}

cars_copy = copy.copy(cars)

for x in cars_copy.keys():
    if x == "model":
        del cars["model"]

print(cars)

Ausgabe:

{'brand': 'Tesla', 'year': 2021, 'color': 'black'}

Eine andere Lösung wäre, eine Kopie der Schlüssel zu erstellen, über die wir dann iterieren können, während wir das Dictionary ändern. Dies kann jedoch nur in Python 2 und nicht in Python 3 funktionieren, da die Schlüssel in Python 3 das Iterable nicht zurückgeben.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021, "color": "black"}

key_copys = list(cars.keys())
print(key_copys)

for key in list(key_copys):
    if cars[key] == "model":
        cars.pop("model")

print(cars)

Beispielausgabe:

['brand', 'model', 'year', 'color']
{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

Umwandeln von Dictionaryelementen in eine Liste

Da wir beim Vornehmen von Änderungen nicht über das Dictionary iterieren können, können wir stattdessen eine Casting-Liste erstellen und über die Liste iterieren, während wir Änderungen am Dictionary vornehmen. Das Durchlaufen der Casting-Liste anstelle des ursprünglichen Dictionaries gibt keinen Laufzeitfehler zurück.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for i in list(cars):
    cars["color"] = "black"

print(cars)

Ausgabe:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

Anhängen von Schlüsseln an eine leere Liste

Um zu vermeiden, dass das Dictionary während der Iteration geändert wird, können wir während der Iteration eine leere Liste mit den Dictionarieschlüsseln erstellen. Mit dieser leeren Liste können wir alle Schlüssel anhängen, die wir entfernen oder ändern möchten, und dann die Funktion pop() verwenden, um die Schlüssel zu entfernen, oder die Funktion append verwenden, um neue Schlüssel-Wert-Paare hinzuzufügen.

Dies kann wie im folgenden Code gezeigt ausgeführt werden.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

list = []

for i in cars:
    list.append(i)

for x in list:
    if x == "model":
        cars.pop(x)

print(cars)

Ausgabe:

{'brand': 'Tesla', 'year': 2021}

Wie unten gezeigt, können wir dem Dictionary ein neues Schlüssel-Wert-Paar hinzufügen, indem wir das gleiche Verfahren verwenden, während wir die for-Schleife verwenden.

Beispielcode:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

list = []

for i in cars:
    list.append(i)

for x in list:
    cars["color"] = "black"

print(cars)

Ausgabe:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}
Autor: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn

Verwandter Artikel - Python Dictionary