Przede wszystkim A.__dict__.__dict__jest inny A.__dict__['__dict__'], a tego pierwszego nie ma. Ten ostatni jest __dict__atrybutem, który miałyby wystąpienia klasy. Jest to obiekt deskryptora, który zwraca wewnętrzny słownik atrybutów dla określonej instancji. Krótko mówiąc, __dict__atrybut obiektu nie może być przechowywany w obiekcie __dict__, więc jest dostępny za pośrednictwem deskryptora zdefiniowanego w klasie.
Aby to zrozumieć, musiałbyś przeczytać dokumentację protokołu deskryptora .
Krótka wersja:
- W przypadku klasy
A, dostęp instance.__dict__jest zapewniany przez A.__dict__['__dict__']to samo, co vars(A)['__dict__'].
- Dla klasy A dostęp
A.__dict__zapewnia type.__dict__['__dict__'](w teorii) to samo, co vars(type)['__dict__'].
Wersja długa:
Zarówno klasy, jak i obiekty zapewniają dostęp do atrybutów zarówno za pośrednictwem operatora atrybutu (zaimplementowanego za pośrednictwem klasy lub metaklasy __getattribute__), jak i __dict__atrybutu / protokołu, który jest używany przez vars(ob).
W przypadku normalnych obiektów __dict__obiekt tworzy oddzielny dictobiekt, który przechowuje atrybuty i __getattribute__najpierw próbuje uzyskać do niego dostęp i stamtąd pobrać atrybuty (przed próbą wyszukania atrybutu w klasie przy użyciu protokołu deskryptora i przed wywołaniem __getattr__). __dict__Deskryptor od klasy implementuje dostęp do tego słownika.
x.namejest równoważne próbuje te w kolejności: x.__dict__['name'], type(x).name.__get__(x, type(x)),type(x).name
x.__dict__ robi to samo, ale pomija pierwszy z oczywistych powodów
Jak to jest możliwe, aby __dict__z instancebyć przechowywane w __dict__instancji, jest on dostępny za pośrednictwem protokołu deskryptora zamiast bezpośrednio, i jest przechowywany w specjalnym polu w instancji.
Podobny scenariusz jest prawdziwy dla klas, chociaż ich __dict__jest specjalnym obiektem proxy, który udaje słownik (ale może nie być wewnętrznie) i nie pozwala na jego zmianę lub zastąpienie innym. To proxy umożliwia między innymi dostęp do atrybutów klasy, które są dla niej specyficzne i nie są zdefiniowane w żadnej z jej baz.
Domyślnie vars(cls)klasa pustej zawiera trzy deskryptory - __dict__do przechowywania atrybutów instancji, __weakref__które są używane wewnętrznie przez weakrefklasę, oraz do jej opisu. Pierwsze dwa mogą zniknąć, jeśli zdefiniujesz __slots__. Wtedy nie miałbyś atrybutów __dict__i __weakref__, ale zamiast tego miałbyś jeden atrybut klasy dla każdego gniazda. Atrybuty instancji nie byłyby wtedy przechowywane w słowniku, a dostęp do nich zapewnią odpowiednie deskryptory w klasie.
I wreszcie, niespójność, która A.__dict__różni się od A.__dict__['__dict__']tego, że atrybut __dict__jest wyjątkowy, nigdy nie jest sprawdzany vars(A), więc to, co jest prawdą, nie jest prawdą dla praktycznie każdego innego atrybutu, którego użyjesz. Na przykład A.__weakref__to to samo, co A.__dict__['__weakref__']. Gdyby ta niespójność nie istniała, używanie A.__dict__nie działałoby i musiałbyś zawsze używać vars(A)zamiast tego.
ive. Przynajmniej sprawiłoby to więcejA.__dict__['ive']pytań;) zobaczę się poza