9 Stimmen

Verwendung eines geordneten Diktats als Objektwörterbuch in Python

Ich weiß nicht, warum das nicht funktioniert:

Ich benutze die odict Klasse von PEP 372 aber ich möchte es als eine __dict__ Mitglied, d.h.:

class Bag(object):
    def __init__(self):
        self.__dict__ = odict()

Aber aus irgendeinem Grund erhalte ich merkwürdige Ergebnisse. Dies funktioniert:

>>> b = Bag()
>>> b.apple = 1
>>> b.apple
1
>>> b.banana = 2
>>> b.banana
2

Aber der Versuch, auf das eigentliche Wörterbuch zuzugreifen, funktioniert nicht:

>>> b.__dict__.items()
[]
>>> b.__dict__
odict.odict([])

Und es wird noch merkwürdiger:

>>> b.__dict__['tomato'] = 3
>>> b.tomato
3
>>> b.__dict__
odict.odict([('tomato', 3)])

Ich komme mir sehr dumm vor. Können Sie mir helfen?

8voto

sykora Punkte 88704

Die beste Antwort auf Ihre Frage, die ich finden konnte, finden Sie unter http://mail.python.org/pipermail/python-bugs-list/2006-April/033155.html .

Im Grunde genommen, wenn __dict__ ist keine tatsächliche dict() wird ignoriert, und die Attributssuche schlägt fehl.

Die Alternative dazu ist, das odict als Mitglied zu verwenden und die Methoden getitem und setitem entsprechend zu überschreiben.

>>> class A(object) :
...     def __init__(self) :
...             self.__dict__['_odict'] = odict()
...     def __getattr__(self, value) :
...             return self.__dict__['_odict'][value]
...     def __setattr__(self, key, value) :
...             self.__dict__['_odict'][key] = value
... 
>>> a = A()
>>> a
<__main__.A object at 0xb7bce34c>
>>> a.x = 1
>>> a.x
1
>>> a.y = 2
>>> a.y
2
>>> a.odict
odict.odict([('x', 1), ('y', 2)])

4voto

Stuart Berg Punkte 15385

Alles in der Antwort von sykora ist richtig. Hier ist eine aktualisierte Lösung mit den folgenden Verbesserungen:

  1. funktioniert auch in dem speziellen Fall des Zugriffs auf a.__dict__ direkt
  2. unterstützt copy.copy()
  3. == y != Betreiber
  4. verwendet collections.OrderedDict von Python 2.7.

...

from collections import OrderedDict

class OrderedNamespace(object):
    def __init__(self):
        super(OrderedNamespace, self).__setattr__( '_odict', OrderedDict() )

    def __getattr__(self, key):
        odict = super(OrderedNamespace, self).__getattribute__('_odict')
        if key in odict:
            return odict[key]
        return super(OrderedNamespace, self).__getattribute__(key)

    def __setattr__(self, key, val):
        self._odict[key] = val

    @property
    def __dict__(self):
        return self._odict

    def __setstate__(self, state): # Support copy.copy
        super(OrderedNamespace, self).__setattr__( '_odict', OrderedDict() )
        self._odict.update( state )

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not self.__eq__(other)

1voto

S Anand Punkte 10166

Wenn Sie nach einer Bibliothek mit Attributzugriff auf OrderedDict suchen, ist die bestelltesattdict Paket bietet dies.

>>> from orderedattrdict import AttrDict
>>> conf = AttrDict()
>>> conf['z'] = 1
>>> assert conf.z == 1
>>> conf.y = 2
>>> assert conf['y'] == 2
>>> conf.x = 3
>>> assert conf.keys() == ['z', 'y', 'x']

Offenlegung: Ich habe diese Bibliothek verfasst. Ich dachte, sie könnte zukünftigen Suchenden helfen.

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