Worin ich die gestellte Frage beantworte
Warum bietet Python es nicht sofort an?
Ich vermute, dass es mit dem Zen von Python zu tun hat : "Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun." Dies würde zwei offensichtliche Möglichkeiten für den Zugriff auf Werte aus Wörterbüchern schaffen: obj['key']
undobj.key
.
Vorsichtsmaßnahmen und Fallstricke
Dazu gehören mögliche Unklarheiten und Verwirrung im Code. dh könnte folgend jemand verwirrend sein sonst wer in wird Ihren Code zu einem späteren Zeitpunkt zu halten oder sogar zu Ihnen, wenn Sie nicht in es für eine Weile zurück. Nochmals aus dem Zen : "Lesbarkeit zählt!"
>>> KEY = 'spam'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Wenn d
instanziiert oder KEY
definiert oder d[KEY]
weit entfernt von wo zugewiesen wirdd.spam
Verwendungsort wird, kann dies leicht zu Verwirrung darüber führen, was getan wird, da dies keine häufig verwendete Redewendung ist. Ich weiß, es könnte mich verwirren.
Wenn Sie den Wert von KEY
wie folgt ändern (aber nicht ändern d.spam
), erhalten Sie jetzt außerdem:
>>> KEY = 'foo'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'C' object has no attribute 'spam'
IMO, die Mühe nicht wert.
Andere Dinge
Wie andere angemerkt haben, können Sie jedes hashbare Objekt (nicht nur eine Zeichenfolge) als Diktatschlüssel verwenden. Zum Beispiel,
>>> d = {(2, 3): True,}
>>> assert d[(2, 3)] is True
>>>
ist legal, aber
>>> C = type('C', (object,), {(2, 3): True})
>>> d = C()
>>> assert d.(2, 3) is True
File "<stdin>", line 1
d.(2, 3)
^
SyntaxError: invalid syntax
>>> getattr(d, (2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
>>>
ist nicht. Auf diese Weise haben Sie Zugriff auf den gesamten Bereich druckbarer Zeichen oder anderer hashbarer Objekte für Ihre Wörterbuchschlüssel, über die Sie beim Zugriff auf ein Objektattribut nicht verfügen. Dies ermöglicht Magie wie eine zwischengespeicherte Objektmetaklasse, wie das Rezept aus dem Python-Kochbuch (Kap. 9) .
Worin ich redaktionell
Ich ziehe die Ästhetik spam.eggs
über spam['eggs']
(ich glaube , es sauberer aussieht), und ich wirklich begonnen , diese Funktionalität Begierde , wenn ich das erfüllt namedtuple
. Aber die Bequemlichkeit, die folgenden Aufgaben ausführen zu können, übertrifft sie.
>>> KEYS = 'spam eggs ham'
>>> VALS = [1, 2, 3]
>>> d = {k: v for k, v in zip(KEYS.split(' '), VALS)}
>>> assert d == {'spam': 1, 'eggs': 2, 'ham': 3}
>>>
Dies ist ein einfaches Beispiel, aber ich benutze häufig Diktate in anderen Situationen als ich obj.key
Notation (dh wenn ich Einstellungen aus einer XML-Datei einlesen muss). In anderen Fällen, in denen ich aus ästhetischen Gründen versucht bin, eine dynamische Klasse zu instanziieren und einige Attribute darauf zu setzen, verwende ich weiterhin ein Diktat für die Konsistenz, um die Lesbarkeit zu verbessern.
Ich bin sicher, dass das OP dies längst zu seiner Zufriedenheit gelöst hat, aber wenn er diese Funktionalität weiterhin möchte, dann schlage ich vor, dass er eines der Pakete von pypi herunterlädt, die es bereitstellen:
Bunch ist derjenige, mit dem ich besser vertraut bin. Unterklasse vondict
, damit Sie alle diese Funktionen haben.
AttrDict sieht auch so aus, als wäre es auch ziemlich gut, aber ich bin nicht so vertraut damit und habe die Quelle nicht so detailliert durchgesehen wie Bunch .
- Addict wird aktiv gepflegt und bietet attr-ähnlichen Zugang und mehr.
- Wie in den Kommentaren von Rotareti erwähnt, ist Bunch veraltet, aber es gibt eine aktive Gabel namens Munch .
Um die Lesbarkeit seines Codes zu verbessern, empfehle ich jedoch dringend, seine Notationsstile nicht zu mischen. Wenn er diese Notation bevorzugt, sollte er einfach ein dynamisches Objekt instanziieren, seine gewünschten Attribute hinzufügen und es einen Tag nennen:
>>> C = type('C', (object,), {})
>>> d = C()
>>> d.spam = 1
>>> d.eggs = 2
>>> d.ham = 3
>>> assert d.__dict__ == {'spam': 1, 'eggs': 2, 'ham': 3}
Wobei ich aktualisiere, um eine Folgefrage in den Kommentaren zu beantworten
In den Kommentaren (unten) fragt Elmo :
Was ist, wenn Sie tiefer gehen möchten? (bezogen auf Typ (...))
Obwohl ich diesen Anwendungsfall noch nie verwendet habe ( dict
aus Konsistenzgründen verwende ich eher verschachtelte ), funktioniert der folgende Code:
>>> C = type('C', (object,), {})
>>> d = C()
>>> for x in 'spam eggs ham'.split():
... setattr(d, x, C())
... i = 1
... for y in 'one two three'.split():
... setattr(getattr(d, x), y, i)
... i += 1
...
>>> assert d.spam.__dict__ == {'one': 1, 'two': 2, 'three': 3}
collections.namedtuple
ist dafür sehr nützlich.