Hier ist meine Version von @derek73 Antwort. Ich verwende dict.__getitem__
als __getattr__
, sodass es immer noch KeyError
wirft, und benenne die öffentlichen Methoden des Wörterbuchs mit ""-Präfix um (um Konflikte mit speziellen Methodennamen zu vermeiden, wie z.B. __get__
, der als Deskriptormethode behandelt werden würde). Wie auch immer, man kann keinen komplett klaren Namensraum für Schlüssel als Attribute haben aufgrund der wichtigen dict
-Basismethoden, daher ist die Lösung nicht perfekt, aber man kann Schlüssel - Attribute wie get
, pop
, items
usw. haben.
class DotDictMeta(type):
def new(
cls,
name,
bases,
attrs,
rename_method=lambda n: f'{n}',
custom_methods,
):
d = dict
attrs.update(
cls.get_hidden_or_renamed_methods(rename_method),
getattr=d.getitem,
setattr=d.setitem,
delattr=d.delitem,
**custom_methods,
)
return super().new(cls, name, bases, attrs)
def __init__(self, name, bases, attrs, **_):
super().__init__(name, bases, attrs)
@property
def attribute_error(self):
raise AttributeError
@classmethod
def get_hidden_or_renamed_methods(cls, rename_method=None):
public_methods = tuple(
i for i in dict.__dict__.items() if not i[0].startswith('__')
)
error = cls.attribute_error
hidden_methods = ((k, error) for k, v in public_methods)
yield from hidden_methods
if rename_method:
renamed_methods = ((rename_method(k), v) for k, v in public_methods)
yield from renamed_methods
class DotDict(dict, metaclass=DotDictMeta):
pass
Du kannst die Wörterbuchmethoden aus dem DotDict-Namensraum entfernen und weiterhin die Methoden der Wörterbuchklasse verwenden. Dies ist auch nützlich, wenn du auf anderen Wörterbuchinstanzen arbeiten möchtest und die gleichen Methoden ohne zusätzliche Überprüfung verwenden möchtest, ob es sich um ein DotDict handelt oder nicht, z.B.
dct = dict(a=1)
dot_dct = DotDict(b=2)
foo = {c: i for i, c in enumerate('xyz')}
for d in (dct, dot_dct):
# Du müsstest dct.update und dot_dct.__update Methoden verwenden
dict.update(d, foo)
assert dict.get(dot, 'foo', 0) is 0**
32 Stimmen
Viele der Situationen, in denen Menschen verschachtelte Dicts verwenden, könnten genauso gut oder sogar besser durch Dicts mit Tupeln als Schlüssel gelöst werden, wobei
d[a][b][c]
durchd[a, b, c]
ersetzt wird.0 Stimmen
Können Sie bitte näher erläutern, wie
d[a][b][c]
durchd[a, b, c]
ersetzt werden kann? Ich habe noch nicht verstanden, wie das gemacht werden kann.9 Stimmen
Es ist kein Zauberei: foo={}; foo[1,2,3] = "one, two, three!"; foo.keys() => [(1,2,3)]
16 Stimmen
Wow. Wow noch einmal. Ich wusste nicht, dass Tupel Schlüssel von Dict sein können. Wow zum dritten Mal.
5 Stimmen
Jedes Objekt, das "hashbar" ist, kann als Schlüssel eines Dicts verwendet werden. Die meisten unveränderlichen Objekte sind auch hashbar, aber nur, wenn alle ihre Inhalte hashbar sind. Der Code d[1, 2, 3] funktioniert, weil "," der "Erstellen eines Tupeloperators" ist; es ist dasselbe wie d[(1, 2, 3)]. Klammern sind häufig optional bei der Deklaration eines Tupels.
0 Stimmen
stackoverflow.com/questions/3031219/… hat eine Antwort, die mehr macht, als Sie wollen.
1 Stimmen
Eine Situation, in der ein Tupel nicht genauso gut ist, json.dumps, TypeError: Schlüssel müssen eine Zeichenfolge sein
0 Stimmen
pypi.python.org/pypi/easydict
0 Stimmen
Bitte sehen Sie auch stackoverflow.com/questions/4984647/…
7 Stimmen
Hast du den Fall in Betracht gezogen, in dem der Schlüssel nur einen Punkt für sich hat -
{"my.key":"value"}
? Oder wenn der Schlüssel ein Schlüsselwort ist, wie z.B. "from"? Ich habe es ein paar Mal in Betracht gezogen, und es bringt mehr Probleme und Fehlerbehebung als wahrgenutzte Vorteile.1 Stimmen
Wenn Sie nicht dazu verpflichtet sind, dict zu verwenden, können Sie stattdessen namedtuple (docs.python.org/2/library/…) verwenden - auf diese Weise können Sie auf seine Elemente über den Punkt (".") zugreifen.
0 Stimmen
Dieser Frage wird auf eine sehr ähnliche Art und Weise vernetzt: Wie man Punkt Notation für ein Wörterbuch in Python verwendet? Diese hat interessante Antworten unter Verwendung von
SimpleNamespace
aus dem integriertentypes
Modul.0 Stimmen
Siehe auch: stackoverflow.com/questions/23463684/…
1 Stimmen
@TodorMinakov einen Punkt in einem Wörterbuchschlüssel zu haben ist genauso üblich wie das Codieren auf einem Bildschirm, der auf den Kopf gestellt ist - und genauso einfach umkehrbar. Außerdem löst es keinerlei Fehler aus, wenn ein Objekt ein
from_whatever
-Attribut hat.