[python] 파이썬 클래스의 __dict __.__ dict__ 속성은 무엇입니까?

>>> class A(object): pass
... 
>>> A.__dict__
<dictproxy object at 0x173ef30>
>>> A.__dict__.__dict__
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
AttributeError: 'dictproxy' object has no attribute '__dict__'
>>> A.__dict__.copy()
{'__dict__': <attribute '__dict__' of 'A' objects> ... }
>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects> # What is this object?

내가 그렇게 A.something = 10하면 A.__dict__. 무엇 이다<attribute '__dict__' of 'A' objects>에서 발견이 A.__dict__.__dict__뭔가를 포함 않을 때, 그리고?



답변

우선는와 A.__dict__.__dict__다르며 A.__dict__['__dict__']전자는 존재하지 않습니다. 후자는 __dict__클래스의 인스턴스가 가질 수 있는 속성입니다. 특정 인스턴스에 대한 속성의 내부 사전을 반환하는 설명자 개체입니다. 간단히 말해 __dict__객체 의 속성은 객체의에 저장할 수 없으므로 __dict__클래스에 정의 된 설명자를 통해 액세스됩니다.

이것을 이해하려면 디스크립터 프로토콜문서 를 읽어야합니다 .

짧은 버전 :

  1. 클래스 인스턴스의 경우에 대한 A액세스 instance.__dict__가 제공되며 A.__dict__['__dict__']이는과 동일합니다 vars(A)['__dict__'].
  2. 클래스 A의 경우에 대한 액세스 A.__dict__type.__dict__['__dict__'](이론상) vars(type)['__dict__'].

긴 버전 :

클래스와 객체 모두 속성 연산자 (클래스 또는 메타 클래스를 통해 구현 __getattribute__됨)와에서 사용하는 __dict__속성 / 프로토콜을 통해 속성에 대한 액세스를 제공합니다 vars(ob).

일반 객체의 경우 __dict__객체 dict는 속성을 저장 하는 별도 의 객체를 만들고 __getattribute__먼저 액세스를 시도하고 거기에서 속성을 가져옵니다 (설명자 프로토콜을 사용하여 클래스에서 속성을 찾으려고 시도하기 전과를 호출하기 전에 __getattr__). __dict__클래스 의 설명자는이 사전에 대한 액세스를 구현합니다.

  • x.name위해 사람들을 시도하는 것과 같습니다 x.__dict__['name'], type(x).name.__get__(x, type(x)),type(x).name
  • x.__dict__ 동일하지만 명백한 이유로 첫 번째 항목을 건너 뜁니다.

__dict__of instance__dict__인스턴스에 저장할 수 없기 때문에 설명자 프로토콜을 통해 직접 액세스하고 인스턴스의 특수 필드에 저장합니다.

클래스의 경우에도 유사한 시나리오가 적용되지만 __dict__, 사전 인 척하는 특수 프록시 개체 (내부적으로는 아닐 수 있음)이며이를 변경하거나 다른 것으로 대체 할 수 없습니다. 이 프록시를 사용하면 무엇보다도 자신에게 고유하고 기본 중 하나에 정의되지 않은 클래스의 속성에 액세스 할 수 있습니다.

기본적으로 vars(cls)비어있는 클래스의 a 는에서 내부적으로 사용 __dict__하는 인스턴스의 속성 과 클래스의 독 스트링 을 저장하기위한 세 개의 설명자를 전달 합니다. 정의하면 처음 두 개가 사라질 수 있습니다 . 그러면 및 속성이 없지만 대신 각 슬롯에 대해 단일 클래스 속성이 있습니다. 그러면 인스턴스의 속성이 사전에 저장되지 않고 클래스의 각 설명자가 액세스 할 수 있습니다.__weakref__weakref__slots____dict____weakref__


그리고 마지막으로, 불일치 A.__dict__다른는 A.__dict__['__dict__']속성이 있기 때문입니다 __dict__입니다, 예외로, 결코 에서 보지 않았다 vars(A)그래서 무엇 마찬가지입니다 것은 당신이 사용하는 거라고 거의 모든 다른 속성에 대한 사실이 아니다. 예를 들어 A.__weakref__A.__dict__['__weakref__']. 이 불일치가 존재하지 않으면 사용 A.__dict__이 작동하지 않으며 항상 vars(A)대신 사용해야 합니다.


답변

속성을 A.__dict__저장하는 딕셔너리 이므로 동일한 속성에 대한 직접 참조 입니다.AA.__dict__['__dict__']A.__dict__

A.__dict__자신에 대한 (종류의) 참조를 포함합니다. “종류”부분은 표현식 이 일반 대신 A.__dict__a dictproxy를 반환하는 이유 dict입니다.

>>> class B(object):
...     "Documentation of B class"
...     pass
...
>>> B.__doc__
'Documentation of B class'
>>> B.__dict__
<dictproxy object at 0x00B83590>
>>> B.__dict__['__doc__']
'Documentation of B class'


답변

탐험을 좀 해보자!

>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects>

그게 뭔지 궁금 해요?

>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>

getset_descriptor개체에는 어떤 속성 이 있습니까?

>>> type(A.__dict__["__dict__"]).__dict__
<dictproxy object at 0xb7efc4ac>

그 사본을 만들면 dictproxy흥미로운 속성, 특히 __objclass____name__.

>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__
(<class '__main__.A'>, '__dict__')

그래서 __objclass__에 대한 참조입니다 A__name__단지 문자열입니다 '__dict__'아마 속성의 이름을?

>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__
True

거기에 있습니다! A.__dict__['__dict__']다시 참조 할 수있는 객체입니다.A.__dict__ .


답변

다음과 같은 간단한 예제를 통해 더 많은 것을 이해할 수 있습니다.

>>> class A(object): pass
... 
>>> a = A()
>>> type(A)
<type 'type'>
>>> type(a)
<class '__main__.A'>
>>> type(a.__dict__)
<type 'dict'>
>>> type(A.__dict__)
<type 'dictproxy'>
>>> type(type.__dict__)
<type 'dictproxy'>
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> type(type.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> a.__dict__ == A.__dict__['__dict__'].__get__(a)
True
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True
>>> a.__dict__ == type.__dict__['__dict__'].__get__(A)['__dict__'].__get__(a)
True

위의 예에서 클래스 객체 속성은 클래스별로 저장되고 클래스의 속성은 메타 클래스 인 클래스별로 저장됩니다. 이것은 또한 다음에 의해 검증됩니다.

>>> a.__dict__ == A.__getattribute__(a, '__dict__')
True
>>> A.__dict__ == type.__getattribute__(A, '__dict__')
True


답변