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 dict
objeto 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 instance
ser 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 weakref
e 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