> **Источник:** https://python-all.ru/3.16/c-api/slots.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

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

Чтобы определить [объекты модулей](https://python-all.ru/3.16/c-api/module.html#moduleobjects) и [классы](https://python-all.ru/3.16/c-api/type.html#creating-heap-types) с помощью C API, можно использовать массив *слотов* – по сути, пары «ключ-значение», описывающие характеристики создаваемого объекта. Это разделяет данные и структуры, используемые во время выполнения, что позволяет CPython – и другим реализациям C API Python – обновлять структуры без нарушения обратной совместимости.

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

- [`PyType_FromSlots()`](https://python-all.ru/3.16/c-api/type.html#c.PyType_FromSlots) для типов;
- [`PyModule_FromSlotsAndSpec()`](https://python-all.ru/3.16/c-api/module.html#c.PyModule_FromSlotsAndSpec) и [хук экспорта расширения](https://python-all.ru/3.16/c-api/extension-modules.html#extension-export-hook) для модулей.

Когда слоты передаются функции, которая их применяет, функция не изменяет массив слотов и любые данные, на которые он указывает (рекурсивно). После завершения функции вызывающий код может изменять или освобождать массив и любые данные, на которые он указывает (рекурсивно), за исключением данных, явно помеченных [`PySlot_STATIC`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot_STATIC).

Если не указано иное, в одном массиве слотов не должно быть нескольких слотов с одинаковым ID ([`sl_id`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot.sl_id)).

Добавлено в версии 3.15: Массивы слотов обобщают более ранний способ определения объектов: с использованием [`PyType_Spec`](https://python-all.ru/3.16/c-api/type.html#c.PyType_Spec) с [`PyType_Slot`](https://python-all.ru/3.16/c-api/type.html#c.PyType_Slot) для типов и [`PyModuleDef`](https://python-all.ru/3.16/c-api/module.html#c.PyModuleDef) с [`PyModuleDef_Slot`](https://python-all.ru/3.16/c-api/module.html#c.PyModuleDef_Slot) для модулей. Более ранний API [мягко устарел](https://python-all.ru/3.16/glossary.html#term-soft-deprecated); планов по его удалению нет.

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

#### `type PySlot`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) (включая все члены) начиная с версии 3.15.*

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

```c
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`

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

- `Py_slot_*` значения, описанные в [Общих идентификаторах слотов](https://python-all.ru/3.16/c-api/slots.html#pyslot-common-ids) ниже;
- `Py_mod_*` значения для модулей, как описано в [Определении модулей](https://python-all.ru/3.16/c-api/module.html#c-module-slots);
- Значения для типов, как описано в [Идентификаторах слотов типов](https://python-all.ru/3.16/c-api/type.html#pyslot-type-slot-ids).

`sl_id`, равный нулю ([`Py_slot_end`](https://python-all.ru/3.16/c-api/slots.html#c.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](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

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

Флаг применяется даже к данным, на которые слот указывает «косвенно», за исключением слотов, вложенных через [`Py_slot_subslots`](https://python-all.ru/3.16/c-api/slots.html#c.Py_slot_subslots), которые могут иметь собственные флаги `PySlot_STATIC`. Например, если применить его к слоту [`Py_tp_members`](https://python-all.ru/3.16/c-api/typeobj.html#c.Py_tp_members), который указывает на массив структур [`PyMemberDef`](https://python-all.ru/3.16/c-api/structures.html#c.PyMemberDef), то весь массив, а также строки имени и документации в его элементах должны быть статическими и константными.

#### `PySlot_INTPTR`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

Этот флаг может упростить перенос из старых структур [`PyType_Slot`](https://python-all.ru/3.16/c-api/type.html#c.PyType_Slot) и [`PyModuleDef_Slot`](https://python-all.ru/3.16/c-api/module.html#c.PyModuleDef_Slot).

#### `PySlot_OPTIONAL`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

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

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

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

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

#### `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](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

Вспомогательные макросы для определения структур `PySlot` с [`sl_id`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot.sl_id) и определённым набором элементов объединения.

`PySlot_STATIC_DATA` устанавливает флаг [`PySlot_STATIC`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot_STATIC); остальные флаги не устанавливают.

Обратите внимание: эти макросы используют *именованные инициализаторы* – возможность языка C, которую C++ добавил в версии 2020 года. Если ваш код должен быть совместим с C++11 или более старыми версиями, используйте [`PySlot_PTR`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot_PTR).

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

```c
#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](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

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

```c
#define PySlot_END {0}
```

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

#### `PySlot_PTR(name, value)`

#### `PySlot_PTR_STATIC(name, value)`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

Вспомогательные макросы для использования в коде, совместимом с C++11. Эта версия C++ не позволяет задавать произвольные элементы объединения в литералах; вместо этого эти макросы устанавливают флаг [`PySlot_INTPTR`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot_INTPTR) и приводят значение к `(void*)`.

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

```c
#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.

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

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

#### `Py_slot_end`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

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

#### `Py_slot_subslots`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

Значение ([`sl_ptr`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot.sl_ptr)) должно указывать на массив структур [`PySlot`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot). Слоты в массиве (до нулевого терминатора, не включая его) будут обрабатываться так, как если бы они были вставлены в текущий массив слотов в точке появления `Py_slot_subslots`.

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

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

#### `Py_slot_invalid`

*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable) начиная с версии 3.15.*

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

При использовании с флагом [`PySlot_OPTIONAL`](https://python-all.ru/3.16/c-api/slots.html#c.PySlot_OPTIONAL) определяет слот без эффекта. Без флага обработка слота с таким идентификатором завершится ошибкой.

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