417 Stimmen

Zugriff auf Diktatschlüssel wie ein Attribut?

Ich finde es bequemer, auf die Diktatschlüssel als obj.foo anstelle von obj['foo'] also habe ich diesen Ausschnitt geschrieben:

class AttributeDict(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __setattr__(self, attr, value):
        self[attr] = value

Ich nehme jedoch an, dass es einen Grund dafür geben muss, dass Python diese Funktionalität nicht von Haus aus bereitstellt. Was wären die Vorbehalte und Fallstricke beim Zugriff auf dict-Schlüssel auf diese Weise?

5voto

s2t2 Punkte 2240

使用方法 SimpleNamespace :

from types import SimpleNamespace

obj = SimpleNamespace(color="blue", year=2050)

print(obj.color) #> "blue"
print(obj.year) #> 2050

EDIT / UPDATE: eine nähere Antwort auf die Frage des Auftraggebers, ausgehend von einem Wörterbuch:

from types import SimpleNamespace

params = {"color":"blue", "year":2020}

obj = SimpleNamespace(**params)

print(obj.color) #> "blue"
print(obj.year) #> 2050

4voto

epool Punkte 6426

Sie können dies mit dieser Klasse tun, die ich gerade erstellt habe. Mit dieser Klasse können Sie die Map Objekt wie ein anderes Wörterbuch (einschließlich json Serialisierung) oder mit der Punktnotation. Ich hoffe, ich kann Ihnen helfen:

class Map(dict):
    """
    Example:
    m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
    """
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self[k] = v

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

Beispiele für den Gebrauch:

m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
# Add new key
m.new_key = 'Hello world!'
print m.new_key
print m['new_key']
# Update values
m.new_key = 'Yay!'
# Or
m['new_key'] = 'Yay!'
# Delete key
del m.new_key
# Or
del m['new_key']

4voto

kadee Punkte 6742

Ich möchte eine weitere Implementierung veröffentlichen, die auf der Antwort von Kinvais aufbaut, aber Ideen aus dem AttributeDict integriert, das in http://databio.org/posts/python_AttributeDict.html .

Der Vorteil dieser Version ist, dass sie auch für verschachtelte Wörterbücher funktioniert:

class AttrDict(dict):
    """
    A class to convert a nested Dictionary into an object with key-values
    that are accessible using attribute notation (AttrDict.attribute) instead of
    key notation (Dict["key"]). This class recursively sets Dicts to objects,
    allowing you to recurse down nested dicts (like: AttrDict.attr.attr)
    """

    # Inspired by:
    # http://stackoverflow.com/a/14620633/1551810
    # http://databio.org/posts/python_AttributeDict.html

    def __init__(self, iterable, **kwargs):
        super(AttrDict, self).__init__(iterable, **kwargs)
        for key, value in iterable.items():
            if isinstance(value, dict):
                self.__dict__[key] = AttrDict(value)
            else:
                self.__dict__[key] = value

4voto

Yuri Astrakhan Punkte 7318

Offenbar gibt es jetzt eine Bibliothek dafür - https://pypi.python.org/pypi/attrdict - das genau diese Funktionalität plus rekursives Zusammenführen und Json-Laden implementiert. Könnte einen Blick wert sein.

4voto

mujjiga Punkte 14580

Das verwende ich

args = {
        'batch_size': 32,
        'workers': 4,
        'train_dir': 'train',
        'val_dir': 'val',
        'lr': 1e-3,
        'momentum': 0.9,
        'weight_decay': 1e-4
    }
args = namedtuple('Args', ' '.join(list(args.keys())))(**args)

print (args.lr)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X