Es gibt potenzielle Probleme, wenn Sie Ihre eigene rekursive Implementierung oder das iterative Äquivalent mit Stack schreiben. Siehe dieses Beispiel:
dic = {}
dic["key1"] = {}
dic["key1"]["key1.1"] = "value1"
dic["key2"] = {}
dic["key2"]["key2.1"] = "value2"
dic["key2"]["key2.2"] = dic["key1"]
dic["key2"]["key2.3"] = dic
Im normalen Sinne ist das verschachtelte Wörterbuch eine n-näre baumähnliche Datenstruktur. Die Definition schließt jedoch nicht die Möglichkeit einer Querkante oder sogar einer Hinterkante (also nicht länger eines Baumes) aus. Hier gilt beispielsweise key2.2 für das Wörterbuch von key1 , key2.3 zeigt auf das gesamte Wörterbuch (Hinterkante / Zyklus). Wenn es eine Hinterkante (Zyklus) gibt, wird der Stapel / die Rekursion unendlich ausgeführt.
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
Wenn Sie dieses Wörterbuch mit dieser Implementierung von Scharron drucken
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
Sie würden diesen Fehler sehen:
RuntimeError: maximum recursion depth exceeded while calling a Python object
Gleiches gilt für die Implementierung von senderle .
Ebenso erhalten Sie mit dieser Implementierung eine Endlosschleife von Fred Foo :
def myprint(d):
stack = list(d.items())
while stack:
k, v = stack.pop()
if isinstance(v, dict):
stack.extend(v.items())
else:
print("%s: %s" % (k, v))
Python erkennt jedoch tatsächlich Zyklen im verschachtelten Wörterbuch:
print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...},
'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
"{...}" ist der Ort, an dem ein Zyklus erkannt wird.
Wie von Moondra gefordert, ist dies eine Möglichkeit, Zyklen (DFS) zu vermeiden:
def myprint(d):
stack = list(d.items())
visited = set()
while stack:
k, v = stack.pop()
if isinstance(v, dict):
if k not in visited:
stack.extend(v.items())
else:
print("%s: %s" % (k, v))
visited.add(k)