2016-06-26 8 views
1

Ich verwende ein Paket, das ein verschachteltes Wörterbuch zurückgibt. Es fühlt sich unbeholfen an, auf dieses Rückgabeobjekt in meinen Klassenmethoden mit der Wörterbuchsyntax zuzugreifen, wenn alles andere in der Objektsyntax ist. Die Suche hat mich zu den Bündel/Neobunch-Paketen gebracht, was zu erreichen scheint, was ich suche. Ich habe auch Nametuples vorgeschlagen, aber diese unterstützen nicht einfach geschachtelte Attribute und die meisten Lösungen verwenden Wörterbücher innerhalb des namedtuple für die Verschachtelung.Objektähnlicher Attributzugriff für verschachteltes Wörterbuch

Was wäre eine natürlichere Art, dies zu erreichen?

data = {'a': 'aval', 'b': {'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}} } 

print(data['b']['b1']['b2a']['b3b']) # dictionary access 
# print(data.b.b1.b2a.b3b) # desired access 

import neobunch 
data1 = neobunch.bunchify(data) 
print(data1.b.b1.b2a.b3b) 

Antwort

2

Die folgende Klasse würden Sie tun, was Sie wollen:

class afoo1(object): 
    def __init__(self, kwargs): 
     for name in kwargs: 
      val = kwargs[name] 
      if isinstance(val, dict): 
       val = afoo1(val) 
      setattr(self,name,val) 

Ich borgen die argparse.Namespace:

class AttrDict(dict): 
    """ Dictionary subclass whose entries can be accessed by attributes 
     (as well as normally). 
    """ 
    def __init__(self, *args, **kwargs): 
     super(AttrDict, self).__init__(*args, **kwargs) 
     self.__dict__ = self 

    @staticmethod 
    def from_nested_dict(data): 
     """ Construct nested AttrDicts from nested dictionaries. """ 
     if not isinstance(data, dict): 
      return data 
     else: 
      return AttrDict({key: AttrDict.from_nested_dict(data[key]) 
           for key in data}) 

data = { 
    "a": "aval", 
    "b": { 
     "b1": { 
      "b2b": "b2bval", 
      "b2a": { 
       "b3a": "b3aval", 
       "b3b": "b3bval" 
      } 
     } 
    } 
} 

data1 = AttrDict.from_nested_dict(data) 
print(data1.b.b1.b2a.b3b) # -> b3bval 
+0

Könnten Sie bitte erläutern, warum/wie der Code funktioniert? Vielen Dank! –

+0

@BartKleijngeld: Welche Rolle (n) verstehst du nicht? – martineau

+0

Ich verstehe nicht, wie die Wörterbuchschlüssel irgendwie Eigenschaften des 'data1' Objekts werden. Ich habe das Gefühl, dass ich etwas sehr Einfaches verpasse, aber ich würde mich freuen, wenn Sie mir diesen Teil erklären könnten :). –

0

Eine einfache Klasse, kann auf dem Grund Objekt gebaut werden Definition, optimiert für die Verschachtelung.

Es würde verwendet werden, wie

In [172]: dd={'a':'aval','b':{'b1':'bval'}} 

In [173]: f=afoo1(dd) 

In [174]: f 
Out[174]: <__main__.afoo1 at 0xb3808ccc> 

In [175]: f.a 
Out[175]: 'aval' 

In [176]: f.b 
Out[176]: <__main__.afoo1 at 0xb380802c> 

In [177]: f.b.b1 
Out[177]: 'bval' 

Es ist auch mit **kwargs (zusammen mit *args) definiert worden sein könnte. Eine __repr__ Definition könnte auch gut sein.

Wie bei anderen einfachen Objekten können Attribute hinzugefügt werden, z. f.c = f (eine rekursive Definition). vars(f) gibt ein Wörterbuch zurück, obwohl es keine rekursive Konvertierung ausführt).

+0

Auch wenn aus Sicht der Funktionalität nichts mit Ihrer Klasse zu tun hat, könnte sie einen besseren Stil haben. Ich würde 'kwargs' nicht für ein normales Wörterbuchargument verwenden, da dieser Parametername normalerweise für Schlüsselwortargumente verwendet wird, was in diesem Kontext überhaupt nicht zutrifft. Ich würde auch 'für Name, Wert in kwargs.items()' (oder '.iteritems()' in Python 2) verwenden, anstatt die Schlüssel zu durchlaufen und den Wert in der nächsten Zeile nachzuschlagen. – Blckknght

+0

Ja, obwohl Fehler das Ergebnis einer unvollständigen Bearbeitung aus dem 'Namespace'-Original sind. – hpaulj

Verwandte Themen