Документация Python неофициальный перевод
Содержание страницы

Слоты определенияDefinition slots

Чтобы определить объекты модулей и классы с помощью C API, можно использовать массив слотов – по сути, пары «ключ-значение», описывающие характеристики создаваемого объекта. Это разделяет данные и структуры, используемые во время выполнения, что позволяет CPython – и другим реализациям C API Python – обновлять структуры без нарушения обратной совместимости.

В этом разделе описаны слоты в общем. Сведения о поведении конкретных объектов и значениях слотов см. в документации функций, которые применяют слоты:

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

Если не указано иное, в одном массиве слотов не должно быть нескольких слотов с одинаковым ID (sl_id).

Добавлено в версии 3.15: Массивы слотов обобщают более ранний способ определения объектов: с использованием PyType_Spec с PyType_Slot для типов и PyModuleDef с PyModuleDef_Slot для модулей. Более ранний API мягко устарел; планов по его удалению нет.

Записи массива слотов используют следующую структуру:

type PySlot
Часть Stable ABI (включая все члены) начиная с версии 3.15.

Запись в массиве слотов. Определяется как:

typedef struct {
    uint16_t sl_id;
    uint16_t sl_flags;
    uint32_t _reserved;  // должно быть 0
    union {
        void *sl_ptr;
        void (*sl_func)(void);
        Py_ssize_t sl_size;
        int64_t sl_int64;
        uint64_t sl_uint64;
    };
} PySlot;
uint16_t sl_id

Идентификатор слота, выбираемый из:

sl_id, равный нулю (Py_slot_end), отмечает конец массива слотов.

void *sl_ptr
void (*sl_func)(void)
Py_ssize_t sl_size
int64_t sl_int64
uint64_t sl_uint64

Данные для слота. Эти поля являются частью анонимного объединения; используемое поле зависит от типа данных, требуемого идентификатором слота: указатель на данные, указатель на функцию, размер, знаковое или беззнаковое целое число соответственно.

Если для конкретного идентификатора слота не указано иное, указатели (т.е. sl_ptr и sl_func) не могут быть NULL.

uint16_t sl_flags

Ноль или более следующих флагов, объединённых операцией ИЛИ:

PySlot_STATIC
Часть Stable ABI начиная с версии 3.15.

Все данные, на которые указывает слот, статически размещены и константны. Таким образом, интерпретатору не нужно копировать эту информацию.

Этот флаг подразумевается для указателей на функции.

Флаг применяется даже к данным, на которые слот указывает «косвенно», за исключением слотов, вложенных через Py_slot_subslots, которые могут иметь собственные флаги PySlot_STATIC. Например, если применить его к слоту Py_tp_members, который указывает на массив структур PyMemberDef, то весь массив, а также строки имени и документации в его элементах должны быть статическими и константными.

PySlot_INTPTR
Часть Stable ABI начиная с версии 3.15.

Данные хранятся в sl_ptr; CPython приведёт их к соответствующему типу.

Этот флаг может упростить перенос из старых структур PyType_Slot и PyModuleDef_Slot.

PySlot_OPTIONAL
Часть Stable ABI начиная с версии 3.15.

Если идентификатор слота неизвестен, интерпретатор должен игнорировать слот, а не завершаться с ошибкой.

Например, если Python 3.16 добавляет новую возможность с новым идентификатором слота,attr соответствующий слот может быть помечен PySlot_OPTIONAL, чтобы Python 3.15 игнорировал его.

Обратите внимание: «опциональность» применяется только к неизвестным идентификаторам слотов. Этот флаг не заставляет Python пропускать недопустимые значения известных слотов.

Добавлено в версии 3.15.

Вспомогательные макросыConvenience macros

PySlot_DATA(name, value)
PySlot_FUNC(name, value)
PySlot_SIZE(name, value)
PySlot_INT64(name, value)
PySlot_UINT64(name, value)
PySlot_STATIC_DATA(name, value)
Часть Stable ABI начиная с версии 3.15.

Вспомогательные макросы для определения структур PySlot с sl_id и определённым набором элементов объединения.

PySlot_STATIC_DATA устанавливает флаг PySlot_STATIC; остальные флаги не устанавливают.

Обратите внимание: эти макросы используют именованные инициализаторы – возможность языка C, которую C++ добавил в версии 2020 года. Если ваш код должен быть совместим с C++11 или более старыми версиями, используйте PySlot_PTR.

Определено как:

#define PySlot_DATA(NAME, VALUE) \
   {.sl_id=NAME, .sl_ptr=(void*)(VALUE)}

#define PySlot_FUNC(NAME, VALUE) \
   {.sl_id=NAME, .sl_func=(VALUE)}

#define PySlot_SIZE(NAME, VALUE) \
   {.sl_id=NAME, .sl_size=(VALUE)}

#define PySlot_INT64(NAME, VALUE) \
   {.sl_id=NAME, .sl_int64=(VALUE)}

#define PySlot_UINT64(NAME, VALUE) \
   {.sl_id=NAME, .sl_uint64=(VALUE)}

#define PySlot_STATIC_DATA(NAME, VALUE) \
   {.sl_id=NAME, .sl_flags=PySlot_STATIC, .sl_ptr=(VALUE)}

Добавлено в версии 3.15.

PySlot_END
Часть Stable ABI начиная с версии 3.15.

Вспомогательный макрос для обозначения конца массива PySlot.

Определено как:

#define PySlot_END {0}

Добавлено в версии 3.15.

PySlot_PTR(name, value)
PySlot_PTR_STATIC(name, value)
Часть Stable ABI начиная с версии 3.15.

Вспомогательные макросы для использования в коде, совместимом с C++11. Эта версия C++ не позволяет задавать произвольные элементы объединения в литералах; вместо этого эти макросы устанавливают флаг PySlot_INTPTR и приводят значение к (void*).

Определено как:

#define PySlot_PTR(NAME, VALUE) \
   {NAME, PySlot_INTPTR, {0}, {(void*)(VALUE)}}

#define PySlot_PTR_STATIC(NAME, VALUE) \
   {NAME, PySlot_INTPTR|Py_SLOT_STATIC, {0}, {(void*)(VALUE)}}

Добавлено в версии 3.15.

Общие идентификаторы слотовCommon slot IDs

Следующие идентификаторы слотов можно использовать как в определениях типов, так и в определениях модулей.

Py_slot_end
Часть Stable ABI начиная с версии 3.15.

Обозначает конец массива слотов. Определено как ноль.

Добавлено в версии 3.15.

Py_slot_subslots
Часть Stable ABI начиная с версии 3.15.

Вложенный массив слотов.

Значение (sl_ptr) должно указывать на массив структур PySlot. Слоты в массиве (до нулевого терминатора, не включая его) будут обрабатываться так, как если бы они были вставлены в текущий массив слотов в точке появления Py_slot_subslots.

Глубина вложенности слотов ограничена 5 уровнями. Это ограничение может быть снято в будущем.

Добавлено в версии 3.15.

Py_slot_invalid
Часть Stable ABI начиная с версии 3.15.

Зарезервировано; всегда будет рассматриваться как неизвестный идентификатор слота. Определяется как UINT16_MAX (0xFFFF).

При использовании с флагом PySlot_OPTIONAL определяет слот без эффекта. Без флага обработка слота с таким идентификатором завершится ошибкой.

Добавлено в версии 3.15.