2013-10-04 13 views
58

Gibt es eine Möglichkeit, ein defaultdict auch als Standard für das defaultdict zu machen? IOW, wenn ich es tue:defaultdict von defaultdict, verschachtelt

x = defaultdict(...stuff...) 
x[0][1][0] 
{} 

Das ist, was ich will. Ich werde wahrscheinlich am Ende das Bündel-Muster verwenden, aber als ich merkte, dass ich nicht wusste, wie ich das machen sollte, hat es mich interessiert.

Also, was ich tun kann:

x = defaultdict(defaultdict) 

aber das ist nur eine Ebene:

x[0] 
{} 
x[0][0] 
KeyError: 0 

Es gibt Rezepte, die dies tun können. Aber kann es einfach mit den normalen defaultdict-Argumenten gemacht werden?

Beachten Sie, dass jemand dies als ein Duplikat von Python: defaultdict of defaultdict? markiert, aber das ist nicht die gleiche Frage ... diese Frage war, wie ein zweistufiges Standarddict zu tun; In diesem Fall wird ein rekursives Standard-Dedikat mit unendlicher Ebene ausgeführt.

+0

Mögliche Duplikat sein [Python: defaultdict von defaultdict] (http://stackoverflow.com/questions/5029934/python-defaultdict-of-defaultdict) – malioboro

+0

Nicht wirklich ... Informationen zu der Frage hinzugefügt, um anzuzeigen, warum. Obwohl das eine nützliche Frage ist. –

Antwort

88

Für eine beliebige Anzahl von Ebenen:

def rec_dd(): 
    return defaultdict(rec_dd) 

>>> x = rec_dd() 
>>> x['a']['b']['c']['d'] 
defaultdict(<function rec_dd at 0x7f0dcef81500>, {}) 
>>> print json.dumps(x) 
{"a": {"b": {"c": {"d": {}}}}} 

Natürlich können Sie auch diese mit einem Lambda tun könnte, aber ich lambdas finden weniger lesbar zu sein. In jedem Fall würde es so aussehen:

rec_dd = lambda: defaultdict(rec_dd) 
+1

In der Tat ein perfektes Beispiel, danke. Könnten Sie es bitte auf den Fall erweitern, dass die Daten von json in das Standarddict von defaultdict geladen werden? –

+0

Eine Anmerkung. Wenn Sie versuchen, diesen Code zu verwenden, während das Beizen von 'Lambda' nicht funktioniert. –

25

Es gibt einen raffinierten Trick besteht darin, dass zu tun:

tree = lambda: defaultdict(tree) 

Dann können Sie erstellen Ihre x mit x = tree().

17

Ähnlich BrenBarn-Lösung, aber nicht den Namen der Variablen tree zweimal enthalten, so dass es funktioniert auch nach Änderungen an der variablen Wörterbuch:

tree = (lambda f: f(f))(lambda a: (lambda: defaultdict(a(a)))) 

Dann können Sie jede neue x mit x = tree() erstellen.


Für die def Version können wir Funktion Schließung Umfang verwenden, um die Datenstruktur von dem Fehler zu schützen, in denen die bestehenden Instanzen arbeiten stoppen, wenn der tree Name Rebound. Es sieht wie folgt aus:

from collections import defaultdict 

def tree(): 
    def the_tree(): 
     return defaultdict(the_tree) 
    return the_tree() 
+4

Ich muss darüber nachdenken (es ist ein wenig komplexer). aber ich denke, dein Punkt ist, dass wenn ich x = tree(), aber dann kommt jemand später und tut Baum = keine, würde dieser noch funktionieren, und das wäre nicht? –

+3

Richtig, das ist mein Punkt. – pts

75

Die anderen Antworten hier sagen Ihnen, wie eine defaultdict zu schaffen, die „unendlich viele“ defaultdict enthält, aber sie nicht zu begegnen, was ich denke, Ihre erste Notwendigkeit gewesen sein, die einfach war zu haben ein zweistufiges Standarddict.

können Sie gesucht haben:

defaultdict(lambda: defaultdict(dict)) 

Die Gründe, warum Sie dieses Konstrukt bevorzugen sind:

  • Es deutlicher als die rekursive Lösung ist, und daher wahrscheinlich besser verständlich die Leser.
  • Dies ermöglicht es dem "Blatt" des defaultdict etwas anderes als ein Wörterbuch, zB ,: defaultdict(lambda: defaultdict(list)) oder defaultdict(lambda: defaultdict(set))
+2

defaultdict (Lambda: defaultdict (Liste)) Die richtige Form? –

+0

Hoppla, ja, die 'Lambda'-Form ist korrekt - weil 'defaultdict (something)' ein wörterbuchähnliches Objekt zurückgibt, aber 'defaultdict' erwartet eine Callable! Vielen Dank! –

+0

Dies wurde als mögliches Duplikat einer anderen Frage markiert ... aber es war nicht meine ursprüngliche Frage. Ich wusste, wie man ein zweistufiges Standarddict erstellt; Was ich nicht wusste, war, wie man es rekursiv macht. Diese Antwort ähnelt in der Tat http://stackoverflow.com/questions/5029934/python-defaultdict-of-defaultdict –

Verwandte Themen