Доступ к атрибутам в Python: сначала слоты, затем дикт?


В приведенном ниже примере атрибут x доступен из слотов объекта, хотя x присутствует в __dict__ (это не типичный или, возможно, полезный случай, но мне любопытно):

>>> class C(object):
...     __slots__ = 'x'
...     
>>> class D(C):
...     pass
... 
>>> obj = D()
>>> obj.x = 'Stored in slots'
>>> obj.__dict__
{}
>>> obj.__dict__['x'] = 'stored in __dict__'
>>> obj.x
'Stored in slots'

Является ли этот порядок доступа (сначала слоты) документированным поведением? или просто деталь реализации?

1 6

1 ответ:

Да, с объектом __dict__ обращаются только после обращения к дескрипторам данных. __slots__ атрибуты реализуются в виде дескрипторов данных.

См. вызов дескрипторов :

Для Привязок, например, приоритет вызова дескриптора зависит от того, какие методы дескриптора определены. Дескриптор может определять любую комбинацию __get__(), __set__() и __delete__(). Если он не определяет __get__(), то доступ к атрибуту вернет дескриптор сам объект, если нет значения в словаре экземпляра объекта. Если дескриптор определяет __set__() и/или __delete__(), то это дескриптор данных; если он не определяет ни того, ни другого, то это не дескриптор данных. Обычно дескрипторы данных определяют как __get__(), так и __set__(), в то время как неданные дескрипторы имеют только метод __get__(). Дескрипторы данных с определениями __set__() и __get__() всегда переопределяют переопределение в словаре экземпляров. Напротив, неданные дескрипторы могут быть переопределены экземпляры.

И с той же страницы, раздел о слотах :

__slots__ реализуются на уровне класса путем создания дескрипторов (реализующих дескрипторы) для каждого имени переменной. В результате атрибуты класса не могут использоваться для задания значений по умолчанию для переменных, определенных в __slots__; в противном случае атрибут класса перезапишет назначение дескриптора.