Атрибут __dict__
должен содержать определенные пользователем атрибуты.
Нет, __dict__
содержит динамические атрибуты объекта. Однако это не единственные атрибуты, которые может иметь объект. Обычно для поиска атрибутов также используется тип объекта.
Например, методы класса можно найти как атрибуты экземпляра. Многие такие атрибуты являются объектами-дескрипторами и привязаны к объект при взгляде вверх. Это работа метода __getattribute__
, который все классы наследуют от object
; атрибуты объекта разрешаются через type(object).__getattribute__(attribute_name)
, после чего учитываются дескрипторы типа, а также атрибуты, непосредственно установленные для объекта (в сопоставлении __dict__
).
Атрибут __bases__
класса предоставляется метатипом класса, который по умолчанию равен type()
; это дескриптор:
>>> class Foo:
... pass
...
>>> Foo.__bases__
(<class 'object'>,)
>>> type.__dict__['__bases__']
<attribute '__bases__' of 'type' objects>
>>> type.__dict__['__bases__'].__get__(Foo, type)
(<class 'object'>,)
__dict__
просто место для хранения атрибутов, которые могут иметь любое допустимое строковое имя. Для классов, которые включают в себя несколько стандартных атрибутов, установленных при создании класса (__module__
и __doc__
), а также другие атрибуты, присутствующие в качестве дескрипторов экземпляров класса (__dict__
и __weakref__
). Последний должен быть добавлен в класс, потому что сам класс также имеет эти атрибуты, взятые из type
, опять же в качестве дескрипторов.
Так почему же __bases__
— это дескриптор, а __doc__
— нет? Вы не можете установить __bases__
на что угодно, поэтому установщик дескриптора проверяет определенные условия и дает возможность перестроить внутренние кэши. Разработчики ядра Python используют дескрипторы, чтобы ограничить то, что может быть установлено, или когда установка значения требует дополнительной работы (например, проверки и обновления внутренних структур).
person
Martijn Pieters
schedule
29.12.2017