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
A
wird 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 dict
Objekt, 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.name
ist ä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 instance
in __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