Вы не можете, в коде Python нет возможности создавать дескрипторы только для чтения, подобные тем, которые используются для __thisclass__
и т. д.
В C API все слоты используют один и тот же тип объекта дескриптора, который становится доступным только для чтения для записей в PyMemberDef
массивы, у которых flags
установлено в READONLY
.
Например. идентифицированные вами дескрипторы super
определены в массиве super_members
а>:
static PyMemberDef super_members[] = {
{"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY,
"the class invoking super()"},
{"__self__", T_OBJECT, offsetof(superobject, obj), READONLY,
"the instance invoking super(); may be None"},
{"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,
"the type of the instance invoking super(); may be None"},
{0}
};
Когда __slots__
обрабатывается, нет пути, по которому вы можете установить этот флаг; код в type.__new__
просто устанавливает первые три значения, то есть name
, type
и offset
соответственно:
mp = PyHeapType_GET_MEMBERS(et);
slotoffset = base->tp_basicsize;
if (et->ht_slots != NULL) {
for (i = 0; i < nslots; i++, mp++) {
mp->name = PyUnicode_AsUTF8(
PyTuple_GET_ITEM(et->ht_slots, i));
if (mp->name == NULL)
goto error;
mp->type = T_OBJECT_EX;
mp->offset = slotoffset;
/* __dict__ and __weakref__ are already filtered out */
assert(strcmp(mp->name, "__dict__") != 0);
assert(strcmp(mp->name, "__weakref__") != 0);
slotoffset += sizeof(PyObject *);
}
}
Для справки:
PyHeapType_GET_MEMBERS
обращается к массиву PyMemberDef
для создаваемого объекта нового типа. Для него уже выделено нужное количество слотов.
et->ht_slots
— это кортеж имен слотов.
slotoffset
— это относительное смещение в области памяти объекта экземпляра для хранения содержимого слота.
- значение
T_OBJECT_EX
для поля type
означает, что слот хранит указатель на объект Python, и если указатель установлен на NULL
, при попытке получить значение поднимается AttributeError
.
Обратите внимание: если бы была возможность сделать эти слоты доступными только для чтения, вам также понадобился бы механизм предоставления их значений перед созданием нового экземпляра! В конце концов, если всему коду Python запретить установку атрибута «только для чтения» для экземпляров, как ваш класс Python вообще сможет установить начальное значение?
person
Martijn Pieters
schedule
09.04.2021