Erstens A.__dict__.__dict__ist anders als A.__dict__['__dict__'], und die erstere existiert nicht. Letzteres ist das __dict__Attribut, das die Instanzen der Klasse haben würden. Es ist ein Deskriptorobjekt, das das interne Wörterbuch der Attribute für die bestimmte Instanz zurückgibt. Kurz gesagt, das __dict__Attribut eines Objekts kann nicht in einem Objekt gespeichert werden __dict__, daher wird auf es über einen in der Klasse definierten Deskriptor zugegriffen.
Um dies zu verstehen, müssen Sie die Dokumentation des Deskriptorprotokolls lesen .
Die Kurzversion:
- Für eine Klasseninstanz
Awird der Zugriff auf instance.__dict__bereitgestellt A.__dict__['__dict__'], der mit identisch ist vars(A)['__dict__'].
- Für die Klasse A wird der Zugriff auf (theoretisch)
A.__dict__durch bereitgestellt, type.__dict__['__dict__']was derselbe ist wie vars(type)['__dict__'].
Die lange Version:
Sowohl Klassen als auch Objekte bieten Zugriff auf Attribute sowohl über den Attributoperator (implementiert über die Klasse oder die Metaklasse __getattribute__) als auch über das __dict__Attribut / Protokoll, das von verwendet wird vars(ob).
Bei normalen Objekten erstellt das __dict__Objekt ein separates dictObjekt, in dem die Attribute gespeichert werden, und __getattribute__versucht zunächst, darauf zuzugreifen und die Attribute von dort abzurufen (bevor versucht wird, das Attribut in der Klasse mithilfe des Deskriptorprotokolls zu suchen, und bevor es aufgerufen wird __getattr__). Der __dict__Deskriptor für die Klasse implementiert den Zugriff auf dieses Wörterbuch.
x.nameist äquivalent zu denen , um versuchen: x.__dict__['name'], type(x).name.__get__(x, type(x)),type(x).name
x.__dict__ macht das gleiche, überspringt aber den ersten aus offensichtlichen Gründen
Da es unmöglich ist, das __dict__of instancein __dict__der Instanz zu speichern , wird stattdessen direkt über das Deskriptorprotokoll darauf zugegriffen und in einem speziellen Feld in der Instanz gespeichert.
Ein ähnliches Szenario gilt für Klassen, obwohl __dict__es sich um ein spezielles Proxy-Objekt handelt, das sich als Wörterbuch ausgibt (möglicherweise jedoch nicht intern) und es Ihnen nicht ermöglicht, es zu ändern oder durch ein anderes zu ersetzen. Mit diesem Proxy können Sie unter anderem auf die Attribute einer Klasse zugreifen, die spezifisch für sie sind und nicht in einer ihrer Basen definiert sind.
Standardmäßig enthält a vars(cls)einer leeren Klasse drei Deskriptoren - __dict__zum Speichern der Attribute der Instanzen, __weakref__die intern von verwendet werden weakref, und der Dokumentzeichenfolge der Klasse. Die ersten beiden könnten weg sein, wenn Sie definieren __slots__. Dann würden Sie nicht haben __dict__und __weakref__Attribute, sondern würden Sie für jeden Steckplatz eine einzige Klasse Attribut haben. Die Attribute der Instanz würden dann nicht in einem Wörterbuch gespeichert, und der Zugriff darauf wird von den jeweiligen Deskriptoren in der Klasse bereitgestellt.
Und schließlich, die Inkonsistenz , die A.__dict__von dem unterscheidet, A.__dict__['__dict__']ist , da das Attribut __dict__ist, ausnahmsweise nie in nachgeschlagen vars(A), so was für sie richtig ist für praktisch jedes andere Attribut nicht wahr ist , dass Sie verwenden würde. Zum Beispiel A.__weakref__ist das gleiche wie A.__dict__['__weakref__']. Wenn diese Inkonsistenz nicht vorhanden A.__dict__wäre, würde die Verwendung nicht funktionieren, und Sie müssten vars(A)stattdessen immer verwenden .
ive. Zumindest hätte es dies zu einer weiterenA.__dict__['ive']Frage gemacht;) Ich werde mich selbst sehen