Em primeiro lugar, A.__dict__.__dict__é diferente de A.__dict__['__dict__'], e o primeiro não existe. O último é o __dict__atributo que as instâncias da classe teriam. É um objeto descritor que retorna o dicionário interno de atributos para a instância específica. Resumindo, o __dict__atributo de um objeto não pode ser armazenado nos objetos __dict__, portanto é acessado por meio de um descritor definido na classe.
Para entender isso, você teria que ler a documentação do protocolo do descritor .
A versão curta:
- Para uma instância de classe
A, o acesso a instance.__dict__é fornecido por A.__dict__['__dict__']qual é o mesmo que vars(A)['__dict__'].
- Para a classe A, o acesso a
A.__dict__é fornecido por type.__dict__['__dict__'](em teoria) que é o mesmo que vars(type)['__dict__'].
A versão longa:
Ambas as classes e objetos fornecem acesso a atributos por meio do operador de atributo (implementado por meio da classe ou metaclasse __getattribute__) e do __dict__atributo / protocolo que é usado por vars(ob).
Para objetos normais, o __dict__objeto cria um dictobjeto separado , que armazena os atributos e __getattribute__primeiro tenta acessá-lo e obter os atributos de lá (antes de tentar procurar o atributo na classe utilizando o protocolo descritor e antes de chamar __getattr__). O __dict__descritor da classe implementa o acesso a este dicionário.
x.nameé equivalente a tentar aqueles em ordem: x.__dict__['name'], type(x).name.__get__(x, type(x)),type(x).name
x.__dict__ faz o mesmo, mas pula o primeiro por razões óbvias
Como é impossível para o __dict__de instanceser armazenado em __dict__da instância, que é acessado através do protocolo descritor diretamente em vez, e é armazenado em um campo especial na instância.
Um cenário semelhante é verdadeiro para classes, embora __dict__sejam um objeto proxy especial que finge ser um dicionário (mas pode não ser internamente) e não permite que você o altere ou substitua por outro. Este proxy permite, entre tudo mais, acessar os atributos de uma classe que lhe são específicos, e não definidos em uma de suas bases.
Por padrão, um vars(cls)de uma classe vazia carrega três descritores - __dict__para armazenar os atributos das instâncias, __weakref__que é usado internamente por weakrefe a docstring da classe. Os dois primeiros podem ter desaparecido se você definir __slots__. Então você não teria os atributos __dict__e __weakref__, mas em vez disso, você teria um único atributo de classe para cada slot. Os atributos da instância não seriam armazenados em um dicionário, e o acesso a eles seria fornecido pelos respectivos descritores da classe.
E, por último, a inconsistência que A.__dict__é diferente de A.__dict__['__dict__']é porque o atributo __dict__, por exceção, nunca é pesquisado vars(A), então o que é verdade para ele não é verdade para praticamente qualquer outro atributo que você usaria. Por exemplo, A.__weakref__é a mesma coisa que A.__dict__['__weakref__']. Se essa inconsistência não existisse, usar A.__dict__não funcionaria e você teria que usar sempre vars(A).
ive. Pelo menos isso teria feito mais umaA.__dict__['ive']pergunta;) Vou me ver sair