Wie mache ich Python-Wörterbuchmitglieder über einen Punkt "." Zugänglich?
Zum Beispiel mydict['val']
möchte ich schreiben , anstatt zu schreiben mydict.val
.
Außerdem möchte ich auf diese Weise auf verschachtelte Diktate zugreifen. Beispielsweise
mydict.mydict2.val
würde sich beziehen
mydict = { 'mydict2': { 'val': ... } }
python
dictionary
syntax
nested
bodacydo
quelle
quelle
d[a][b][c]
die durch ersetzt werdend[a, b, c]
.{"my.key":"value"}
? Oder wenn der Schlüssel ein Schlüsselwort ist, wie "von"? Ich habe ein paar Mal darüber nachgedacht, und es sind mehr Probleme und Fehlerbehebung als wahrgenommene Vorteile.Antworten:
Sie können es mit dieser Klasse machen, die ich gerade gemacht habe. Mit dieser Klasse können Sie das
Map
Objekt wie ein anderes Wörterbuch (einschließlich JSON-Serialisierung) oder mit der Punktnotation verwenden. Ich hoffe Dir zu helfen:Anwendungsbeispiele:
quelle
.iteritems()
auf.items()
AttributeError
wenn das Attribut nicht vorhanden ist. Stattdessen wird es zurückkehrenNone
.self.update(*args,**kwargs)
. Sie können auch hinzufügen__missing__(self,key): value=self[key]= type(self)(); return value
. Anschließend können Sie fehlende Einträge in Punktnotation hinzufügen. Wenn Sie möchten, dass es auswählbar ist, können Sie hinzufügen__getstate__
und__setstate__
hasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding
__getattr__`Ich habe das immer in einer Util-Datei aufbewahrt. Sie können es auch als Mixin für Ihre eigenen Klassen verwenden.
quelle
d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.bar
löst einen Attributfehler aus,d.foo
funktioniert aber einwandfrei.python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
get
es in der Tat eine schlechte Idee zu sein, da es zurückkehren wird,None
anstatt einen Fehler für fehlende GegenständeInstallieren
dotmap
überpip
Es macht alles, was Sie wollen, und Unterklassen
dict
, so dass es wie ein normales Wörterbuch funktioniert:Darüber hinaus können Sie es in und aus
dict
Objekten konvertieren :Das heißt, wenn etwas, auf das Sie zugreifen möchten, bereits in
dict
Form ist, können Sie es in einenDotMap
für den einfachen Zugriff umwandeln:Schließlich werden automatisch neue untergeordnete
DotMap
Instanzen erstellt, sodass Sie folgende Aktionen ausführen können:Vergleich mit Bunch
Vollständige Offenlegung: Ich bin der Schöpfer der DotMap . Ich habe es erstellt, weil
Bunch
diese Funktionen fehltenDotMap
Erstellung, die Zeit spart und saubereren Code sorgt, wenn Sie viel Hierarchie habendict
und rekursives Konvertieren aller untergeordnetendict
Instanzen inDotMap
quelle
{"test.foo": "bar"}
kann über erreicht werdenmymap.test.foo
Das wäre fantastisch. Es wird einige Regressionen erfordern, um eine flache Karte in eine tiefe Karte umzuwandeln und dann DotMap darauf anzuwenden, aber es lohnt sich!DotMap
mit Autocomplete am besten funktioniert. Ich verwende Sublime Text, der zuvor eingegebene Schlüsselwörter automatisch vervollständigt.**kwargs
oder gibtc = {**a, **b}
. Tatsächlich schlägt es leise fehl und verhält sich beim Extrahieren wie ein leeres Wörterbuch.m = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));
und ich habe das erwartet bekommen2 3
. Wenn Sie einen nachweislich fehlerhaften Fall haben, der funktioniert,dict()
aber nichtDotMap()
, senden Sie Ihren Code bitte an die Registerkarte Probleme in GitHub.Ableiten von diktieren und implementieren
__getattr__
und__setattr__
.Oder Sie können Bunch verwenden, das sehr ähnlich ist.
Ich denke nicht, dass es möglich ist, eine eingebaute Diktatklasse zu monkeypatchen.
quelle
Stoff hat eine wirklich schöne, minimale Implementierung . Wenn Sie dies erweitern, um einen verschachtelten Zugriff zu ermöglichen, können Sie a verwenden.
defaultdict
Das Ergebnis sieht ungefähr so aus:Nutzen Sie es wie folgt:
Das geht ein wenig auf Kugel's Antwort von ein "Ableiten von diktieren und implementieren
__getattr__
und__setattr__
" ein. Jetzt weißt du wie!quelle
dotdict
, mit der vorhandenedict
Objekte rekursiv konvertiert werden können: gist.github.com/miku/…Ich habe es versucht:
Du kannst es versuchen
__getattribute__
.Machen Sie jedes Diktat zu einer Art Dotdict. Wenn Sie dies aus einem mehrschichtigen Diktat heraus initiieren möchten, versuchen Sie es
__init__
ebenfalls.quelle
def docdict(name):
davor platziere und dann "if isinstance (name, dict): DotDict (name) return name"class dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
Tu es nicht. Attributzugriff und Indizierung sind in Python getrennte Dinge, und Sie sollten nicht möchten, dass sie dieselbe Leistung erbringen. Erstellen Sie eine Klasse (möglicherweise eine von
namedtuple
), wenn Sie etwas haben, das über zugängliche Attribute verfügen sollte, und verwenden Sie die[]
Notation, um ein Element aus einem Diktat zu erhalten.quelle
.
anstatt[]
auf komplizierte Datenstrukturen in Mako-Vorlagen zuzugreifen.Wenn Sie Ihr modifiziertes Wörterbuch auswählen möchten, müssen Sie den obigen Antworten einige Statusmethoden hinzufügen:
quelle
__getattr__ = dict.get
Aufbauend auf Kugel's Antwort und unter Berücksichtigung von Mike Grahams warnenden Worten, was ist, wenn wir eine Verpackung herstellen?
quelle
Verwendung
SimpleNamespace
:quelle
Ich mag den Munch und er bietet viele praktische Optionen zusätzlich zum Punktzugriff.
quelle
Ich bin kürzlich auf die Box gestoßen -Bibliothek , die das Gleiche tut.
Installationsbefehl:
pip install python-box
Beispiel:
Ich fand es effektiver als andere vorhandene Bibliotheken wie Dotmap, die Python-Rekursionsfehler erzeugen, wenn Sie große verschachtelte Dicts haben.
Link zur Bibliothek und Details: https://pypi.org/project/python-box/
quelle
Die Verwendung
__getattr__
funktioniert sehr einfach in Python 3.4.3Ausgabe:
quelle
Die Sprache selbst unterstützt dies nicht, aber manchmal ist dies immer noch eine nützliche Voraussetzung. Neben dem Bunch-Rezept können Sie auch eine kleine Methode schreiben, mit der Sie mithilfe einer gepunkteten Zeichenfolge auf ein Wörterbuch zugreifen können:
was so etwas unterstützen würde:
quelle
Um auf der Antwort von epool aufzubauen, können Sie mit dieser Version über den Punktoperator auf jedes Diktat im Inneren zugreifen:
Gibt zum Beispiel
foo.bar.baz[1].baba
zurück"loo"
.quelle
iteritems()
durchitems()
undxrange()
mitrange()
Wenn man sich entscheidet, das dauerhaft
dict
in ein Objekt umzuwandeln, sollte dies reichen. Sie können unmittelbar vor dem Zugriff ein Wegwerfobjekt erstellen.quelle
Am Ende habe ich sowohl das AttrDict als auch das Bunch ausprobiertBibliotheken und fand sie viel zu langsam für meine Zwecke. Nachdem ein Freund und ich uns damit befasst hatten, stellten wir fest, dass die Hauptmethode zum Schreiben dieser Bibliotheken dazu führt, dass die Bibliothek aggressiv durch ein verschachteltes Objekt rekursiert und durchgehend Kopien des Wörterbuchobjekts erstellt. Vor diesem Hintergrund haben wir zwei wichtige Änderungen vorgenommen. 1) Wir haben Attribute faul geladen. 2) Anstatt Kopien eines Wörterbuchobjekts zu erstellen, erstellen wir Kopien eines leichten Proxy-Objekts. Dies ist die endgültige Implementierung. Die Leistungssteigerung bei der Verwendung dieses Codes ist unglaublich. Bei Verwendung von AttrDict oder Bunch haben diese beiden Bibliotheken allein 1/2 bzw. 1/3 meiner Anforderungszeit in Anspruch genommen (was!?). Dieser Code reduzierte diese Zeit auf fast nichts (irgendwo im Bereich von 0,5 ms). Dies hängt natürlich von Ihren Anforderungen ab, aber wenn Sie diese Funktionalität in Ihrem Code häufig verwenden,
Die ursprüngliche Implementierung finden Sie hier unter https://stackoverflow.com/users/704327/michael-merickel .
Die andere Sache zu beachten ist, dass diese Implementierung ziemlich einfach ist und nicht alle Methoden implementiert, die Sie möglicherweise benötigen. Sie müssen diese nach Bedarf in die DictProxy- oder ListProxy-Objekte schreiben.
quelle
Ich möchte meine eigene Lösung in den Ring werfen:
https://github.com/skorokithakis/jsane
Sie können JSON in etwas analysieren, auf das Sie zugreifen können
with.attribute.lookups.like.this.r()
, hauptsächlich, weil ich diese Antwort nicht gesehen habe, bevor ich mit der Arbeit begonnen habe.quelle
KeyError
ist einer davon. Wenn man auf den Schlüssel zugreift, der nicht existiert, muss man nurNone
ähnlich wie JS zurückgeben. Ich bin ein großer Fan von Autovivifizierung sowohl zum Lesen als auch zum Schreiben. Ihre Bibliothek ist dem Ideal am nächsten.Keine direkte Antwort auf die Frage des OP, aber inspiriert von und vielleicht nützlich für einige. Ich habe eine objektbasierte Lösung unter Verwendung des internen
__dict__
(in keiner Weise optimierten Codes) erstellt.quelle
Eine einfache Möglichkeit, Punktzugriff (aber keinen Arrayzugriff) zu erhalten, besteht darin, ein einfaches Objekt in Python zu verwenden. So was:
... und benutze es so:
... um es in ein Diktat umzuwandeln:
quelle
Diese Lösung ist eine Weiterentwicklung der von epool angebotenen Lösung , um die Anforderung des OP zu erfüllen, auf konsistente Weise auf verschachtelte Dikte zuzugreifen. Die Lösung von epool erlaubte keinen Zugriff auf verschachtelte Dikte.
Mit dieser Klasse kann man jetzt so etwas machen wie :
A.B.C.D
.quelle
Dies funktioniert auch mit verschachtelten Dikten und stellt sicher, dass sich später angehängte Dikte gleich verhalten:
quelle
Die Antwort von @ derek73 ist sehr ordentlich, kann jedoch weder eingelegt noch (tief) kopiert werden und wird
None
für fehlende Schlüssel zurückgegeben. Der folgende Code behebt dies.Bearbeiten: Ich habe die Antwort oben nicht gesehen , die genau den gleichen Punkt anspricht (positiv bewertet). Ich lasse die Antwort hier als Referenz.
quelle
Eine Lösung, die irgendwie heikel ist
quelle