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

Структуры объектов типаType Object Structures

Пожалуй, одна из самых важных структур объектной системы Python – это структура, определяющая новый тип: структура PyTypeObject. Объекты типа можно обрабатывать с помощью любой из функций PyObject_* или PyType_*, но для большинства приложений Python они не представляют большого интереса. Эти объекты являются основой поведения объектов, поэтому они очень важны как для самого интерпретатора, так и для любых модулей расширения, реализующих новые типы.

Объекты типа довольно велики по сравнению с большинством стандартных типов. Причина такого размера в том, что каждый объект типа хранит большое количество значений, в основном указателей на функции C, каждый из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно рассматриваются в этом разделе. Поля будут описаны в порядке их появления в структуре.

В дополнение к следующему краткому справочнику раздел Примеры даёт представление о значении и использовании PyTypeObject.

Краткий справочникQuick Reference

“tp slots”

PyTypeObject Slot [1]

Тип

специальные методы/атрибуты

Информация [2]

O

T

D

I

<R> tp_name

const char *

name

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

destructor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

getattribute__, __getattr

G

(tp_setattr)

setattrfunc

setattr__, __delattr

G

tp_as_async

PyAsyncMethods *

подслоты

%

tp_repr

reprfunc

repr

X

X

X

tp_as_number

PyNumberMethods *

подслоты

%

tp_as_sequence

PySequenceMethods *

подслоты

%

tp_as_mapping

PyMappingMethods *

подслоты

%

tp_hash

hashfunc

hash

X

G

tp_call

ternaryfunc

call

X

X

tp_str

reprfunc

str

X

X

tp_getattro

getattrofunc

getattribute__, __getattr

X

X

G

tp_setattro

setattrofunc

setattr__, __delattr

X

X

G

tp_as_buffer

PyBufferProcs *

%

tp_flags

unsigned long

X

X

?

tp_doc

const char *

doc

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

lt__, __le__, __eq__, __ne__, __gt__, __ge

X

G

(tp_weaklistoffset)

Py_ssize_t

X

?

tp_iter

getiterfunc

iter

X

tp_iternext

iternextfunc

next

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

base

X

tp_dict

PyObject *

dict

?

tp_descr_get

descrgetfunc

get

X

tp_descr_set

descrsetfunc

set__, __delete

X

(tp_dictoffset)

Py_ssize_t

X

?

tp_init

initproc

init

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

new

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases>

PyObject *

bases

~

<tp_mro>

PyObject *

mro

~

[tp_cache]

PyObject *

[tp_subclasses]

void *

subclasses

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

del

X

tp_vectorcall

vectorcallfunc

[tp_watched]

unsigned char

подслотыsub-slots

Слот

Тип

специальные методы

am_await

unaryfunc

await

am_aiter

unaryfunc

aiter

am_anext

unaryfunc

anext

am_send

sendfunc

nb_add

binaryfunc

add__ __radd

nb_inplace_add

binaryfunc

iadd

nb_subtract

binaryfunc

sub__ __rsub

nb_inplace_subtract

binaryfunc

isub

nb_multiply

binaryfunc

mul__ __rmul

nb_inplace_multiply

binaryfunc

imul

nb_remainder

binaryfunc

mod__ __rmod

nb_inplace_remainder

binaryfunc

imod

nb_divmod

binaryfunc

divmod__ __rdivmod

nb_power

ternaryfunc

pow__ __rpow

nb_inplace_power

ternaryfunc

ipow

nb_negative

unaryfunc

neg

nb_positive

unaryfunc

pos

nb_absolute

unaryfunc

abs

nb_bool

inquiry

bool

nb_invert

unaryfunc

invert

nb_lshift

binaryfunc

lshift__ __rlshift

nb_inplace_lshift

binaryfunc

ilshift

nb_rshift

binaryfunc

rshift__ __rrshift

nb_inplace_rshift

binaryfunc

irshift

nb_and

binaryfunc

and__ __rand

nb_inplace_and

binaryfunc

iand

nb_xor

binaryfunc

xor__ __rxor

nb_inplace_xor

binaryfunc

ixor

nb_or

binaryfunc

or__ __ror

nb_inplace_or

binaryfunc

ior

nb_int

unaryfunc

int

nb_reserved

void *

nb_float

unaryfunc

float

nb_floor_divide

binaryfunc

floordiv

nb_inplace_floor_divide

binaryfunc

ifloordiv

nb_true_divide

binaryfunc

truediv

nb_inplace_true_divide

binaryfunc

itruediv

nb_index

unaryfunc

index

nb_matrix_multiply

binaryfunc

matmul__ __rmatmul

nb_inplace_matrix_multiply

binaryfunc

imatmul

mp_length

lenfunc

len

mp_subscript

binaryfunc

getitem

mp_ass_subscript

objobjargproc

setitem__, __delitem

sq_length

lenfunc

len

sq_concat

binaryfunc

add

sq_repeat

ssizeargfunc

mul

sq_item

ssizeargfunc

getitem

sq_ass_item

ssizeobjargproc

setitem__ __delitem

sq_contains

objobjproc

contains

sq_inplace_concat

binaryfunc

iadd

sq_inplace_repeat

ssizeargfunc

imul

bf_getbuffer

getbufferproc()

bf_releasebuffer

releasebufferproc()

Синонимы типов слотовslot typedefs

typedef

Типы параметров

Тип возвращаемого значения

allocfunc

PyObject *

destructor

PyObject *

void

freefunc

void *

void

traverseproc

void *

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

const char *

PyObject *

setattrfunc

const char *

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

int

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

int

releasebufferproc

void

inquiry

PyObject *

int

unaryfunc

PyObject *

binaryfunc

PyObject *

ternaryfunc

PyObject *

ssizeargfunc

PyObject *

ssizeobjargproc

int

objobjproc

int

objobjargproc

int

Подробнее см. определения типов слотов ниже.

Определение PyTypeObjectPyTypeObject Definition

Определение структуры для PyTypeObject можно найти в Include/cpython/object.h. Для удобства здесь повторяется определение, приведённое там:

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* Для вывода в формате "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* Для выделения памяти */

    /* Методы для реализации стандартных операций */

    destructor tp_dealloc;
    Py_ssize_t tp_vectorcall_offset;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    PyAsyncMethods *tp_as_async; /* ранее известный как tp_compare (Python 2)
                                    или tp_reserved (Python 3) */
    reprfunc tp_repr;

    /* Наборы методов для стандартных классов */

    PyNumberMethods *tp_as_number;
    PySequenceMethods *tp_as_sequence;
    PyMappingMethods *tp_as_mapping;

    /* Дополнительные стандартные операции (здесь для двоичной совместимости) */

    hashfunc tp_hash;
    ternaryfunc tp_call;
    reprfunc tp_str;
    getattrofunc tp_getattro;
    setattrofunc tp_setattro;

    /* Функции для доступа к объекту как к буферу ввода/вывода */
    PyBufferProcs *tp_as_buffer;

    /* Флаги для определения наличия опциональных/расширенных возможностей */
    unsigned long tp_flags;

    const char *tp_doc; /* Строка документации */

    /* Назначенное значение в версии 2.0 */
    /* вызов функции для всех доступных объектов */
    traverseproc tp_traverse;

    /* удаление ссылок на содержащиеся объекты */
    inquiry tp_clear;

    /* Назначенное значение в версии 2.1 */
    /* расширенные сравнения */
    richcmpfunc tp_richcompare;

    /* включение слабых ссылок */
    Py_ssize_t tp_weaklistoffset;

    /* Итераторы */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Дескриптор атрибутов и механизмы подклассов */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    // Сильная ссылка на тип в куче, заимствованная ссылка на статический тип
    struct _typeobject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    Py_ssize_t tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Низкоуровневая процедура освобождения памяти */
    inquiry tp_is_gc; /* Для PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* порядок разрешения методов */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

    /* Метка версии кэша атрибутов типа. Добавлено в версии 2.6. */
    unsigned int tp_version_tag;

    destructor tp_finalize;
    vectorcallfunc tp_vectorcall;

    /* битовый набор, указывающий, какие наблюдатели типов следят за этим типом */
    unsigned char tp_watched;
} PyTypeObject;

Слоты PyObjectPyObject Slots

Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (создаваемых с помощью type_new(), обычно вызываемого из инструкции class). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, что означает, что его экземпляры (т.е. объекты типов) должны иметь поле ob_size.

Py_ssize_t PyObject.ob_refcnt
Часть Stable ABI.

Это счётчик ссылок объекта-типа, инициализируется значением 1 макросом PyObject_HEAD_INIT. Обратите внимание: для статически выделенных объектов-типов экземпляры типа (объекты, у которых ob_type указывает обратно на тип) не считаются ссылками. Но для динамически выделенных объектов-типов экземпляры действительно считаются ссылками.

Наследование:

Это поле не наследуется подтипами.

PyTypeObject *PyObject.ob_type
Часть Stable ABI.

Это тип типа, иными словами, его метатип. Он инициализируется аргументом макроса PyObject_HEAD_INIT, и его значением обычно должно быть &PyType_Type. Однако для динамически загружаемых модулей расширения, которые должны работать на Windows (по крайней мере), компилятор сообщает, что это недопустимый инициализатор. Поэтому принято передавать NULL макросу PyObject_HEAD_INIT и явно инициализировать это поле в начале функции инициализации модуля, перед любыми другими действиями. Обычно это делается так:

Foo_Type.ob_type = &PyType_Type;

Это должно быть сделано до создания любых экземпляров типа. PyType_Ready() проверяет, равен ли ob_type значению NULL, и если да, инициализирует его значением поля ob_type базового класса. PyType_Ready() не будет изменять это поле, если оно ненулевое.

Наследование:

Это поле наследуется подтипами.

PyObject *PyObject._ob_next
PyObject *PyObject._ob_prev

Эти поля присутствуют только если определён макрос Py_TRACE_REFS (см. configure --with-trace-refs option).

Их инициализация значением NULL выполняется макросом PyObject_HEAD_INIT. Для статически размещённых объектов эти поля всегда остаются NULL. Для динамически размещённых объектов эти два поля используются для включения объекта в двусвязный список всех живых объектов в куче.

Это можно использовать для различных целей отладки; в настоящее время используется только в функции sys.getobjects() и для вывода объектов, которые остаются живыми в конце выполнения, когда установлена переменная окружения PYTHONDUMPREFS.

Наследование:

Эти поля не наследуются подтипами.

Слоты PyVarObjectPyVarObject Slots

Py_ssize_t PyVarObject.ob_size
Часть Stable ABI.

Для статически выделенных объектов типов это поле должно быть инициализировано нулём. Для динамически выделенных объектов типов это поле имеет особый внутренний смысл.

Доступ к этому полю должен осуществляться с помощью макросов Py_SIZE() и Py_SET_SIZE().

Наследование:

Это поле не наследуется подтипами.

Слоты PyTypeObjectPyTypeObject Slots

Каждый слот имеет раздел, описывающий наследование. Если PyType_Ready() может устанавливать значение, когда поле установлено в NULL, то также будет раздел «Default» (значение по умолчанию). (Обратите внимание, что многие поля, заданные в PyBaseObject_Type и PyType_Type, фактически действуют как значения по умолчанию.)

const char *PyTypeObject.tp_name

Указатель на строку, завершающуюся NUL, содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, за которым следует точка, а затем имя типа; для встроенных типов это должно быть просто имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип с именем T, определённый в модуле M в подпакете Q пакета P, должен иметь инициализатор tp_name со значением "P.Q.M.T".

Для динамически выделенных объектов типов это должно быть просто имя типа, а имя модуля должно быть явно сохранено в словаре типа как значение для ключа '__module__'.

Для статически размещённых объектов типов, поле tp_name должно содержать точку. Всё до последней точки становится доступно как атрибут __module__, а всё после последней точки – как атрибут __name__.

Если точка отсутствует, всё поле tp_name становится доступным как атрибут __name__, а атрибут __module__ не определён (если только не задан явно в словаре, как описано выше). Это означает, что ваш тип невозможно будет сериализовать с помощью pickle. Кроме того, он не будет отображаться в документации модуля, создаваемой pydoc.

Это поле не должно быть NULL. Это единственное обязательное поле в PyTypeObject() (кроме потенциально tp_itemsize).

Наследование:

Это поле не наследуется подтипами.

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

Эти поля позволяют вычислить размер экземпляров типа в байтах.

Существует два вида типов: типы с экземплярами фиксированной длины имеют нулевое поле tp_itemsize, типы с экземплярами переменной длины имеют ненулевое поле tp_itemsize. Для типа с экземплярами фиксированной длины все экземпляры имеют одинаковый размер, заданный в tp_basicsize. (Исключения из этого правила могут быть сделаны с помощью PyUnstable_Object_GC_NewWithExtraData().)

Для типа с экземплярами переменной длины экземпляры должны иметь поле ob_size, а размер экземпляра равен tp_basicsize плюс N раз tp_itemsize, где N – это «длина» объекта.

Функции, подобные PyObject_NewVar(), принимают значение N в качестве аргумента и сохраняют его в поле ob_size экземпляра. Обратите внимание, что поле ob_size впоследствии может использоваться для других целей. Например, экземпляры int используют биты ob_size в определённом реализацией способе; доступ к нижележащему хранилищу и его размеру следует осуществлять с помощью PyLong_Export().

Примечание

К полю ob_size следует обращаться с помощью макросов Py_SIZE() и Py_SET_SIZE().

Кроме того, наличие поля ob_size в структуре экземпляра не означает, что структура экземпляра имеет переменную длину. Например, тип list имеет экземпляры фиксированной длины, но эти экземпляры содержат поле ob_size. (Как и в случае с int, избегайте прямого чтения ob_size списков. Вместо этого вызывайте PyList_Size().)

Поле tp_basicsize включает размер, необходимый для данных tp_base типа, а также любые дополнительные данные, необходимые каждому экземпляру.

Правильный способ установки tp_basicsize – использовать оператор sizeof для структуры, используемой для объявления структуры экземпляра. Эта структура должна включать структуру, используемую для объявления базового типа. Другими словами, tp_basicsize должно быть больше или равно tp_basicsize базового типа.

Поскольку каждый тип является подтипом object, эта структура должна включать PyObject или PyVarObject (в зависимости от того, должен ли быть включён ob_size). Обычно они определяются макросом PyObject_HEAD или PyObject_VAR_HEAD соответственно.

Базовый размер не включает размер заголовка GC, поскольку этот заголовок не является частью PyObject_HEAD.

Для случаев, когда структура, используемая для объявления базового типа, неизвестна, см. PyType_Spec.basicsize и PyType_FromMetaclass().

Примечания о выравнивании:

  • tp_basicsize должно быть кратно _Alignof(PyObject). При использовании sizeof в struct, включающем PyObject_HEAD, как рекомендуется, компилятор обеспечивает это. При отказе от C-структуры struct или при использовании расширений компилятора, таких как __attribute__((packed)), ответственность ложится на вас.

  • Если элементы переменной части требуют определённого выравнивания, tp_basicsize и tp_itemsize должны быть кратны этому выравниванию. Например, если переменная часть типа хранит double, вы обязаны убедиться, что оба поля кратны _Alignof(double).

Наследование:

Эти поля наследуются подтипами по отдельности. (То есть, если поле установлено в ноль, PyType_Ready() скопирует значение из базового типа, указывая, что экземпляры не нуждаются в дополнительном хранилище.)

Если базовый тип имеет ненулевое tp_itemsize, обычно небезопасно устанавливать tp_itemsize в другое ненулевое значение в подтипе (хотя это зависит от реализации базового типа).

destructor PyTypeObject.tp_dealloc

Указатель на функцию-деструктор экземпляра. Эта функция должна быть определена, если только тип не гарантирует, что его экземпляры никогда не будут освобождены (как в случае с синглетонами None и Ellipsis). Сигнатура функции:

void tp_dealloc(PyObject *self);

Функция-деструктор вызывается макросами Py_DECREF() и Py_XDECREF(), когда новое значение счётчика ссылок становится нулевым. В этот момент экземпляр всё ещё существует, но на него нет ссылок. Функция-деструктор должна освободить все ссылки, которыми владеет экземпляр, освободить все буферы памяти, принадлежащие экземпляру (с использованием функции освобождения, соответствующей функции выделения, использованной для выделения буфера), и вызвать функцию tp_free типа. Если тип не является субтипируемым (не имеет установленного флага Py_TPFLAGS_BASETYPE), допускается вызывать деаллокатор объекта напрямую, а не через tp_free. Деаллокатор объекта должен быть тем же, что использовался для выделения экземпляра; обычно это PyObject_Del(), если экземпляр был выделен с помощью PyObject_New или PyObject_NewVar, или PyObject_GC_Del(), если экземпляр был выделен с помощью PyObject_GC_New или PyObject_GC_NewVar.

Если тип поддерживает сборку мусора (имеет установленный флаг Py_TPFLAGS_HAVE_GC ), деструктор должен вызвать PyObject_GC_UnTrack() перед очисткой любых полей-членов.

static void foo_dealloc(foo_object *self) {
    PyObject_GC_UnTrack(self);
    Py_CLEAR(self->ref);
    Py_TYPE(self)->tp_free((PyObject *)self);
}

Наконец, если тип выделен в куче (Py_TPFLAGS_HEAPTYPE), деаллокатор должен освободить принадлежащую ему ссылку на объект-тип (через Py_DECREF()) после вызова деаллокатора типа. Чтобы избежать висячих указателей, рекомендуемый способ сделать это:

static void foo_dealloc(foo_object *self) {
    PyTypeObject *tp = Py_TYPE(self);
    // Освободить ссылки и буферы здесь.
    tp->tp_free(self);
    Py_DECREF(tp);
}

Предупреждение

В Python со сборкой мусора tp_dealloc может вызываться из любого потока Python, а не только из потока, создавшего объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Это не проблема для вызовов API Python, поскольку поток, в котором вызывается tp_dealloc, будет владеть Глобальной блокировкой интерпретатора (GIL). Однако, если уничтожаемый объект в свою очередь уничтожает объекты из какой-либо другой библиотеки C или C++, следует проявить осторожность, чтобы уничтожение этих объектов в потоке, вызвавшем tp_dealloc, не нарушило никаких предположений библиотеки.

Наследование:

Это поле наследуется подтипами.

Py_ssize_t PyTypeObject.tp_vectorcall_offset

Необязательное смещение к поинстансной функции, реализующей вызов объекта с помощью протокола vectorcall, более эффективная альтернатива более простому tp_call.

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

Указатель vectorcallfunc может быть NULL, и в этом случае экземпляр ведёт себя так, как если бы Py_TPFLAGS_HAVE_VECTORCALL не был установлен: вызов экземпляра сводится к tp_call.

Любой класс, устанавливающий Py_TPFLAGS_HAVE_VECTORCALL, должен также установить tp_call и убедиться, что его поведение согласуется с функцией vectorcallfunc. Это можно сделать, установив tp_call в PyVectorcall_Call().

Изменено в версии 3.8: До версии 3.8 этот слот назывался tp_print. В Python 2.x он использовался для вывода в файл. В Python 3.0–3.7 он не использовался.

Изменено в версии 3.12: До версии 3.12 не рекомендовалось для изменяемых типов, размещаемых в куче реализовывать протокол vectorcall. Когда пользователь устанавливает __call__ в коде Python, обновляется только tp_call, что, вероятно, делает его несовместимым с функцией vectorcall. Начиная с версии 3.12, установка __call__ отключает оптимизацию vectorcall путём сброса флага Py_TPFLAGS_HAVE_VECTORCALL.

Наследование:

Это поле всегда наследуется. Однако флаг Py_TPFLAGS_HAVE_VECTORCALL наследуется не всегда. Если он не установлен, то подкласс не будет использовать vectorcall, за исключением случаев, когда PyVectorcall_Call() вызывается явно.

getattrfunc PyTypeObject.tp_getattr

Необязательный указатель на функцию получения строки атрибута.

Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция tp_getattro, но принимает C-строку вместо строкового объекта Python для указания имени атрибута.

Наследование:

Группа: tp_getattr, tp_getattro

Это поле наследуется подтипами вместе с tp_getattro: подтип наследует и tp_getattr, и tp_getattro от своего базового типа, когда tp_getattr и tp_getattro подтипа оба равны NULL.

setattrfunc PyTypeObject.tp_setattr

Необязательный указатель на функцию для установки и удаления атрибутов.

Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция tp_setattro, но принимает C-строку вместо строкового объекта Python для указания имени атрибута.

Наследование:

Группа: tp_setattr, tp_setattro

Это поле наследуется подтипами вместе с tp_setattro: подтип наследует и tp_setattr, и tp_setattro от своего базового типа, когда tp_setattr и tp_setattro подтипа оба равны NULL.

PyAsyncMethods *PyTypeObject.tp_as_async

Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протоколы ожидаемого объекта и асинхронного итератора на уровне C. Подробнее см. в Структуры асинхронных объектов.

Добавлено в версии 3.5: Ранее было известно как tp_compare и tp_reserved.

Наследование:

Поле tp_as_async не наследуется, но содержащиеся в нем поля наследуются по отдельности.

reprfunc PyTypeObject.tp_repr

Необязательный указатель на функцию, реализующую встроенную функцию repr().

Сигнатура такая же, как для PyObject_Repr():

PyObject *tp_repr(PyObject *self);

Функция должна возвращать строку или объект Unicode. В идеале она должна возвращать строку, которая при передаче в eval() в подходящем окружении возвращает объект с тем же значением. Если это невозможно, она должна возвращать строку, начинающуюся с '<' и заканчивающуюся '>', из которой можно вывести как тип, так и значение объекта.

Наследование:

Это поле наследуется подтипами.

По умолчанию:

Если это поле не задано, возвращается строка вида <%s object at %p>, где %s заменяется именем типа, а %p – адресом памяти объекта.

PyNumberMethods *PyTypeObject.tp_as_number

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

Наследование:

Поле tp_as_number не наследуется, но содержащиеся в нём поля наследуются по отдельности.

PySequenceMethods *PyTypeObject.tp_as_sequence

Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протокол последовательности. Эти поля описаны в Структуры объектов-последовательностей.

Наследование:

Поле tp_as_sequence не наследуется, но содержащиеся в нём поля наследуются по отдельности.

PyMappingMethods *PyTypeObject.tp_as_mapping

Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протокол отображения. Эти поля описаны в Структуры объектов-отображений.

Наследование:

Поле tp_as_mapping не наследуется, но содержащиеся в нём поля наследуются по отдельности.

hashfunc PyTypeObject.tp_hash

Необязательный указатель на функцию, реализующую встроенную функцию hash().

Сигнатура такая же, как для PyObject_Hash():

Py_hash_t tp_hash(PyObject *);

Значение -1 не должно возвращаться как обычное возвращаемое значение; при возникновении ошибки во время вычисления хеш-значения функция должна установить исключение и вернуть -1.

Если это поле не задано (и tp_richcompare не задано), то попытка получить хеш объекта вызывает TypeError. Это то же самое, что установить его в PyObject_HashNotImplemented().

Это поле можно явно установить в PyObject_HashNotImplemented(), чтобы заблокировать наследование хеш-метода от родительского типа. Это интерпретируется как эквивалент __hash__ = None на уровне Python, в результате чего isinstance(o, collections.Hashable) корректно возвращает False. Обратите внимание, что верно и обратное: установка __hash__ = None в классе на уровне Python приведет к тому, что слот tp_hash будет установлен в PyObject_HashNotImplemented().

Наследование:

Группа: tp_hash, tp_richcompare

Это поле наследуется подтипами вместе с tp_richcompare: подтип наследует как tp_richcompare, так и tp_hash, если tp_richcompare и tp_hash подтипа равны NULL.

ternaryfunc PyTypeObject.tp_call

Необязательный указатель на функцию, реализующую вызов объекта. Это значение должно быть NULL, если объект не является вызываемым. Сигнатура такая же, как у PyObject_Call():

PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);

Наследование:

Это поле наследуется подтипами.

reprfunc PyTypeObject.tp_str

Необязательный указатель на функцию, реализующую встроенную операцию str(). (Обратите внимание, что str теперь является типом, а str() вызывает конструктор этого типа. Этот конструктор вызывает PyObject_Str() для выполнения фактической работы, и PyObject_Str() будет вызывать этот обработчик.)

Сигнатура такая же, как для PyObject_Str():

PyObject *tp_str(PyObject *self);

Функция должна возвращать строку или объект Unicode. Это должно быть «дружественное» строковое представление объекта, так как это представление будет использоваться, в частности, функцией print().

Наследование:

Это поле наследуется подтипами.

По умолчанию:

Если это поле не задано, вызывается PyObject_Repr() для возврата строкового представления.

getattrofunc PyTypeObject.tp_getattro

Необязательный указатель на функцию получения атрибута.

Сигнатура такая же, как для PyObject_GetAttr():

PyObject *tp_getattro(PyObject *self, PyObject *attr);

Обычно удобно установить это поле в PyObject_GenericGetAttr(), которое реализует обычный способ поиска атрибутов объекта.

Наследование:

Группа: tp_getattr, tp_getattro

Это поле наследуется подтипами вместе с tp_getattr: подтип наследует и tp_getattr, и tp_getattro от своего базового типа, когда tp_getattr и tp_getattro подтипа оба равны NULL.

По умолчанию:

PyBaseObject_Type использует PyObject_GenericGetAttr().

setattrofunc PyTypeObject.tp_setattro

Необязательный указатель на функцию для установки и удаления атрибутов.

Сигнатура такая же, как для PyObject_SetAttr():

int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);

Кроме того, установка value в NULL для удаления атрибута должна поддерживаться. Обычно удобно устанавливать это поле в PyObject_GenericSetAttr(), которое реализует обычный способ установки атрибутов объекта.

Наследование:

Группа: tp_setattr, tp_setattro

Это поле наследуется подтипами вместе с tp_setattr: подтип наследует и tp_setattr, и tp_setattro от своего базового типа, когда tp_setattr и tp_setattro подтипа оба равны NULL.

По умолчанию:

PyBaseObject_Type использует PyObject_GenericSetAttr().

PyBufferProcs *PyTypeObject.tp_as_buffer

Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих буферный интерфейс. Эти поля описаны в Buffer Object Structures.

Наследование:

Поле tp_as_buffer не наследуется, но содержащиеся в нем поля наследуются по отдельности.

unsigned long PyTypeObject.tp_flags

Это поле представляет собой битовую маску различных флагов. Некоторые флаги указывают на изменённую семантику для определённых ситуаций; другие используются для указания того, что определённые поля в объекте типа (или в расширяющих структурах, на которые ссылаются через tp_as_number, tp_as_sequence, tp_as_mapping и tp_as_buffer), которые исторически не всегда присутствовали, теперь действительны; если такой бит флага сброшен, то поля типа, которые он защищает, не должны использоваться и должны считаться имеющими значение ноль или NULL.

Наследование:

Наследование этого поля устроено сложно. Большинство битов флагов наследуются индивидуально: если у базового типа установлен бит флага, подтип наследует этот бит. Биты флагов, относящиеся к структурам расширения, наследуются строго вместе с самой структурой расширения – значение бита флага базового типа копируется в подтип вместе с указателем на структуру расширения. Бит флага Py_TPFLAGS_HAVE_GC наследуется вместе с полями tp_traverse и tp_clear: если в подтипе бит Py_TPFLAGS_HAVE_GC сброшен, а поля tp_traverse и tp_clear в подтипе существуют и имеют значения NULL. .. XXX действительно ли большинство битов флагов наследуются индивидуально?

По умолчанию:

PyBaseObject_Type использует Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.

Битовые маски:

В настоящее время определены следующие битовые маски; их можно объединять с помощью оператора | для получения значения поля tp_flags. Макрос PyType_HasFeature() принимает тип и значение флагов, tp и f, и проверяет, является ли tp->tp_flags & f ненулевым.

Py_TPFLAGS_HEAPTYPE

Этот бит устанавливается, когда сам объект типа выделяется в куче, например, типы, созданные динамически с помощью PyType_FromSpec(). В этом случае поле ob_type его экземпляров считается ссылкой на тип, и объект типа инкрементируется (INCREF) при создании нового экземпляра, и декрементируется (DECREF) при уничтожении экземпляра (это не относится к экземплярам подтипов; только тип, на который ссылается ob_type экземпляра, инкрементируется или декрементируется). Типы в куче также должны поддерживать сборку мусора так как они могут образовывать циклические ссылки с собственным объектом модуля.

Наследование:

???

Py_TPFLAGS_BASETYPE

Этот бит устанавливается, когда тип может использоваться как базовый тип другого типа. Если этот бит сброшен, тип не может быть унаследован (аналогично «финальному» классу в Java).

Наследование:

???

Py_TPFLAGS_READY

Этот бит устанавливается, когда объект типа был полностью инициализирован функцией PyType_Ready().

Наследование:

???

Py_TPFLAGS_READYING

Этот бит устанавливается, пока PyType_Ready() находится в процессе инициализации объекта типа.

Наследование:

???

Py_TPFLAGS_HAVE_GC

Этот бит устанавливается, когда объект поддерживает сборку мусора. Если бит установлен, экземпляры должны создаваться с помощью PyObject_GC_New и уничтожаться с помощью PyObject_GC_Del(). Дополнительная информация – в разделе Поддержка циклической сборки мусора. Этот бит также означает, что связанные со сборкой мусора поля tp_traverse и tp_clear присутствуют в объекте типа.

Наследование:

Группа: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Бит флага Py_TPFLAGS_HAVE_GC наследуется вместе с полями tp_traverse и tp_clear, то есть если бит флага Py_TPFLAGS_HAVE_GC сброшен в подтипе, а поля tp_traverse и tp_clear в подтипе существуют и имеют значения NULL.

Py_TPFLAGS_DEFAULT

Это битовая маска всех битов, относящихся к наличию определённых полей в объекте типа и его структурах расширения. В настоящее время она включает следующие биты: Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.

Наследование:

???

Py_TPFLAGS_METHOD_DESCRIPTOR

Этот бит указывает, что объекты ведут себя как несвязанные методы.

Если этот флаг установлен для type(meth), то:

  • meth.__get__(obj, cls)(*args, **kwds) (при obj не None) должен быть эквивалентен meth(obj, *args, **kwds).

  • meth.__get__(None, cls)(*args, **kwds) должен быть эквивалентен meth(*args, **kwds).

Этот флаг включает оптимизацию для типичных вызовов методов, таких как obj.meth(): он позволяет избежать создания временного объекта «связанный метод» для obj.meth.

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

Наследование:

Этот флаг никогда не наследуется типами, у которых не установлен флаг Py_TPFLAGS_IMMUTABLETYPE. Для типов расширения он наследуется всякий раз, когда наследуется tp_descr_get.

Py_TPFLAGS_MANAGED_DICT

This bit indicates that instances of the class have a ~object.__dict__ attribute, and that the space for the dictionary is managed by the VM.

Если этот флаг установлен, Py_TPFLAGS_HAVE_GC также должен быть установлен.

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

Наследование:

Этот флаг наследуется, если только поле tp_dictoffset не установлено в суперклассе.

Py_TPFLAGS_MANAGED_WEAKREF

Этот бит указывает, что экземпляры класса должны поддерживать слабые ссылки.

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

Наследование:

Этот флаг наследуется, если только поле tp_weaklistoffset не установлено в суперклассе.

Py_TPFLAGS_ITEMS_AT_END

Применим только к типам переменного размера, то есть с ненулевым tp_itemsize.

Указывает, что часть переменного размера экземпляра этого типа находится в конце области памяти экземпляра, со смещением Py_TYPE(obj)->tp_basicsize (которое может отличаться в каждом подклассе).

При установке этого флага убедитесь, что все суперклассы либо используют такое же расположение в памяти, либо не являются типами переменного размера. Python не проверяет это условие.

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

Наследование:

Этот флаг наследуется.

Py_TPFLAGS_LONG_SUBCLASS
Py_TPFLAGS_LIST_SUBCLASS
Py_TPFLAGS_TUPLE_SUBCLASS
Py_TPFLAGS_BYTES_SUBCLASS
Py_TPFLAGS_UNICODE_SUBCLASS
Py_TPFLAGS_DICT_SUBCLASS
Py_TPFLAGS_BASE_EXC_SUBCLASS
Py_TPFLAGS_TYPE_SUBCLASS

These flags are used by functions such as PyLong_Check() to quickly determine if a type is a subclass of a built-in type; such specific checks are faster than a generic check, like PyObject_IsInstance(). Custom types that inherit from built-ins should have their tp_flags set appropriately, or the code that interacts with such types will behave differently depending on what kind of check is used.

Py_TPFLAGS_HAVE_FINALIZE

Этот бит устанавливается, когда слот tp_finalize присутствует в структуре типа.

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

Устарело с версии 3.8: Этот флаг больше не нужен, так как интерпретатор предполагает, что слот tp_finalize всегда присутствует в структуре типа.

Py_TPFLAGS_HAVE_VECTORCALL

Этот бит устанавливается, когда класс реализует протокол vectorcall. Подробнее см. tp_vectorcall_offset.

Наследование:

Этот бит наследуется, если tp_call также наследуется.

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

Изменено в версии 3.12: Теперь этот флаг удаляется из класса, когда __call__() методу класса присваивается новое значение.

Теперь этот флаг может наследоваться изменяемыми классами.

Py_TPFLAGS_IMMUTABLETYPE

Этот бит устанавливается для объектов типа, которые являются неизменяемыми: атрибуты типа нельзя ни установить, ни удалить.

PyType_Ready() автоматически применяет этот флаг к статическим типам.

Наследование:

Этот флаг не наследуется.

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

Py_TPFLAGS_DISALLOW_INSTANTIATION

Запретить создание экземпляров типа: установить tp_new в NULL и не создавать ключ __new__ в словаре типа.

Флаг должен быть установлен до создания типа, а не после. Например, его нужно установить до вызова PyType_Ready() для этого типа.

Флаг устанавливается автоматически для статических типов, если tp_base равен NULL или &PyBaseObject_Type, и tp_new равен NULL.

Наследование:

Этот флаг не наследуется. Однако подклассы нельзя будет инстанцировать, если они не предоставят ненулевой tp_new (что возможно только через C API).

Примечание

Чтобы запретить прямое создание экземпляров класса, но разрешить создание его подклассов (например, для абстрактного базового класса), не используйте этот флаг. Вместо этого добейтесь, чтобы tp_new завершался успешно только для подклассов.

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

Py_TPFLAGS_MAPPING

Этот бит указывает, что экземпляры класса могут сопоставляться с шаблонами отображений при использовании в качестве объекта оператора match. Он автоматически устанавливается при регистрации или наследовании collections.abc.Mapping и сбрасывается при регистрации collections.abc.Sequence.

Примечание

Py_TPFLAGS_MAPPING и Py_TPFLAGS_SEQUENCE взаимоисключающие; одновременная активация обоих флагов является ошибкой.

Наследование:

Этот флаг наследуется типами, которые ещё не установили Py_TPFLAGS_SEQUENCE.

См. также

PEP 634 – Структурное сопоставление с образцом: спецификация

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

Py_TPFLAGS_SEQUENCE

Этот бит указывает, что экземпляры класса могут сопоставляться с шаблонами последовательностей при использовании в качестве объекта оператора match. Он автоматически устанавливается при регистрации или наследовании collections.abc.Sequence и сбрасывается при регистрации collections.abc.Mapping.

Примечание

Py_TPFLAGS_MAPPING и Py_TPFLAGS_SEQUENCE взаимоисключающие; одновременная активация обоих флагов является ошибкой.

Наследование:

Этот флаг наследуется типами, которые ещё не установили Py_TPFLAGS_MAPPING.

См. также

PEP 634 – Структурное сопоставление с образцом: спецификация

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

Py_TPFLAGS_VALID_VERSION_TAG

Внутренний флаг. Не устанавливайте и не сбрасывайте этот флаг. Чтобы указать, что класс изменился, вызовите PyType_Modified()

Предупреждение

This flag is present in header files, but is an internal feature and should not be used. It will be removed in a future version of CPython

const char *PyTypeObject.tp_doc

Необязательный указатель на C-строку, завершающуюся символом NUL, содержащую строку документации для данного объекта типа. Он доступен как атрибут __doc__ у типа и его экземпляров.

Наследование:

Это поле не наследуется подтипами.

traverseproc PyTypeObject.tp_traverse

Необязательный указатель на функцию обхода для сборщика мусора. Используется только если установлен бит флага Py_TPFLAGS_HAVE_GC. Сигнатура:

int tp_traverse(PyObject *self, visitproc visit, void *arg);

Дополнительная информация о схеме сборки мусора в Python доступна в разделе Поддержка циклической сборки мусора.

Указатель tp_traverse используется сборщиком мусора для обнаружения циклических ссылок. Типичная реализация функции tp_traverse просто вызывает Py_VISIT() для каждого элемента экземпляра, являющегося объектом Python, которым владеет экземпляр. Например, это функция local_traverse() из модуля расширения _thread:

static int
local_traverse(localobject *self, visitproc visit, void *arg)
{
    Py_VISIT(self->args);
    Py_VISIT(self->kw);
    Py_VISIT(self->dict);
    return 0;
}

Обратите внимание, что Py_VISIT() вызывается только для тех членов, которые могут участвовать в циклических ссылках. Хотя есть также член self->key, он может быть только NULL или строкой Python и поэтому не может быть частью циклической ссылки.

С другой стороны, даже если известно, что член никогда не может быть частью цикла, в качестве средства отладки его всё равно можно обойти, чтобы функция get_referents() модуля gc включила его.

Предупреждение

При реализации tp_traverse должны обходиться только те члены, которыми экземпляр владеет (имея на них сильные ссылки). Например, если объект поддерживает слабые ссылки через слот tp_weaklist, указатель, поддерживающий связанный список (то, на что указывает tp_weaklist), не должен обходиться, поскольку экземпляр не владеет напрямую слабыми ссылками на себя (список слабых ссылок существует для поддержки механизма слабых ссылок, но у экземпляра нет сильной ссылки на элементы внутри него, так как они могут быть удалены, даже если экземпляр всё ещё жив).

Обратите внимание, что Py_VISIT() требует, чтобы параметры visit и arg для local_traverse() имели именно такие имена; не следует называть их как попало.

Экземпляры кучевых типов содержат ссылку на свой тип. Поэтому их функция обхода должна либо обходить Py_TYPE(self), либо делегировать эту ответственность путём вызова tp_traverse другого кучевого типа (например, кучевого суперкласса). Если этого не сделать, объект типа может не быть собран сборщиком мусора.

Изменено в версии 3.9: Ожидается, что типы, выделяемые в куче, будут посещать Py_TYPE(self) в tp_traverse. В более ранних версиях Python из-за ошибки 40217 это могло приводить к сбоям в подклассах.

Наследование:

Группа: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Это поле наследуется подтипами вместе с tp_clear и флагом Py_TPFLAGS_HAVE_GC: флаг, tp_traverse и tp_clear наследуются от базового типа, если они равны нулю в подтипе.

inquiry PyTypeObject.tp_clear

Необязательный указатель на функцию очистки для сборщика мусора. Используется только если установлен флаг Py_TPFLAGS_HAVE_GC. Сигнатура:

int tp_clear(PyObject *);

Функция-член tp_clear используется для разрыва циклических ссылок в циклическом мусоре, обнаруженном сборщиком мусора. В совокупности все функции tp_clear в системе должны совместно разрывать все циклические ссылки. Это тонкий момент, и при любых сомнениях следует предоставить функцию tp_clear. Например, тип tuple не реализует функцию tp_clear, поскольку можно доказать, что ни одна циклическая ссылка не может состоять исключительно из кортежей. Поэтому функции tp_clear других типов должны быть достаточны для разрыва любой циклической ссылки, содержащей кортеж. Это не очевидно, и редко есть веская причина избегать реализации tp_clear.

Реализации tp_clear должны удалять ссылки экземпляра на те его члены, которые могут являться объектами Python, и устанавливать указатели на эти члены в NULL, как показано в следующем примере:

static int
local_clear(localobject *self)
{
    Py_CLEAR(self->key);
    Py_CLEAR(self->args);
    Py_CLEAR(self->kw);
    Py_CLEAR(self->dict);
    return 0;
}

Следует использовать макрос Py_CLEAR(), потому что очистка ссылок – это деликатная операция: ссылка на содержащийся объект не должна освобождаться (через Py_DECREF()) до тех пор, пока указатель на содержащийся объект не будет установлен в NULL. Это связано с тем, что освобождение ссылки может привести к тому, что содержащийся объект станет мусором, что вызовет цепочку действий по его утилизации, которая может включать выполнение произвольного кода Python (из-за финализаторов или колбэков слабых ссылок, связанных с содержащимся объектом). Если такой код может снова сослаться на self, важно, чтобы указатель на содержащийся объект в этот момент был NULL, чтобы self знал, что содержащийся объект больше нельзя использовать. Макрос Py_CLEAR() выполняет операции в безопасном порядке.

Обратите внимание, что tp_clear вызывается не всегда перед освобождением экземпляра. Например, когда подсчёта ссылок достаточно, чтобы определить, что объект больше не используется, циклический сборщик мусора не задействуется, и tp_dealloc вызывается напрямую.

Поскольку цель функций tp_clear – разрывать циклические ссылки, нет необходимости очищать содержащиеся объекты, такие как строки Python или целые числа Python, которые не могут участвовать в циклических ссылках. С другой стороны, может быть удобно очистить все содержащиеся объекты Python и написать функцию tp_dealloc типа так, чтобы она вызывала tp_clear.

Дополнительную информацию о схеме сборки мусора Python можно найти в разделе Поддержка циклической сборки мусора.

Наследование:

Группа: Py_TPFLAGS_HAVE_GC, tp_traverse, tp_clear

Это поле наследуется подтипами вместе с tp_traverse и флагом Py_TPFLAGS_HAVE_GC: флаг, tp_traverse и tp_clear наследуются от базового типа, если они равны нулю в подтипе.

richcmpfunc PyTypeObject.tp_richcompare

Необязательный указатель на функцию расширенного сравнения, сигнатура которой:

PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);

Первый параметр гарантированно является экземпляром типа, определяемого через PyTypeObject.

Функция должна возвращать результат сравнения (обычно Py_True или Py_False). Если сравнение не определено, она должна вернуть Py_NotImplemented; если произошла другая ошибка, она должна вернуть NULL и установить условие исключения.

Следующие константы определены для использования в качестве третьего аргумента для tp_richcompare и для PyObject_RichCompare():

Константа

Сравнение

Py_LT

<

Py_LE

<=

Py_EQ

==

Py_NE

!=

Py_GT

>

Py_GE

>=

Для упрощения написания функций расширенного сравнения определён следующий макрос:

Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

Возвращает Py_True или Py_False из функции в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочиваемыми с помощью операторов сравнения языка C (например, это могут быть значения типа int или float). Третий аргумент задаёт требуемую операцию, как и для PyObject_RichCompare().

Возвращаемое значение – это новая сильная ссылка.

В случае ошибки устанавливает исключение и возвращает NULL из функции.

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

Наследование:

Группа: tp_hash, tp_richcompare

Это поле наследуется подтипами вместе с tp_hash: подтип наследует tp_richcompare и tp_hash, когда tp_richcompare и tp_hash подтипа оба NULL.

По умолчанию:

PyBaseObject_Type предоставляет реализацию tp_richcompare, которая может быть унаследована. Однако, если определено только tp_hash, унаследованная функция не используется, и экземпляры типа не смогут участвовать в сравнениях.

Py_ssize_t PyTypeObject.tp_weaklistoffset

Хотя это поле всё ещё поддерживается, Py_TPFLAGS_MANAGED_WEAKREF следует использовать вместо него, если это возможно.

Если экземпляры этого типа поддерживают слабые ссылки, это поле больше нуля и содержит смещение в структуре экземпляра до головы списка слабых ссылок (игнорируя заголовок GC, если он присутствует); это смещение используется функциями PyObject_ClearWeakRefs() и PyWeakref_*. Структура экземпляра должна содержать поле типа PyObject*, которое инициализируется NULL.

Не путайте это поле с tp_weaklist; это голова списка для слабых ссылок на сам объект типа.

Установка обоих битов Py_TPFLAGS_MANAGED_WEAKREF и tp_weaklistoffset является ошибкой.

Наследование:

Это поле наследуется подтипами, но см. правила ниже. Подтип может переопределить это смещение; это означает, что подтип использует другую голову списка слабых ссылок, нежели базовый тип. Поскольку голова списка всегда находится через tp_weaklistoffset, это не должно быть проблемой.

По умолчанию:

Если бит Py_TPFLAGS_MANAGED_WEAKREF установлен в поле tp_flags, то tp_weaklistoffset будет установлено в отрицательное значение, чтобы указать, что использовать это поле небезопасно.

getiterfunc PyTypeObject.tp_iter

Необязательный указатель на функцию, возвращающую итератор для объекта. Его наличие обычно означает, что экземпляры этого типа являются итерируемыми (хотя последовательности могут быть итерируемыми и без этой функции).

Эта функция имеет ту же сигнатуру, что и PyObject_GetIter():

PyObject *tp_iter(PyObject *self);

Наследование:

Это поле наследуется подтипами.

iternextfunc PyTypeObject.tp_iternext

Необязательный указатель на функцию, возвращающую следующий элемент итератора. Сигнатура:

PyObject *tp_iternext(PyObject *self);

Когда итератор исчерпан, он должен возвращать NULL; исключение StopIteration может быть установлено или нет. При другой ошибке он также должен возвращать NULL. Его наличие означает, что экземпляры этого типа являются итераторами.

Типы-итераторы также должны определять функцию tp_iter, и эта функция должна возвращать сам экземпляр итератора (не новый экземпляр итератора).

Эта функция имеет ту же сигнатуру, что и PyIter_Next().

Наследование:

Это поле наследуется подтипами.

struct PyMethodDef *PyTypeObject.tp_methods

Необязательный указатель на статический массив структур PyMethodDef, завершающийся NULL, объявляющий обычные методы этого типа.

Для каждой записи в массиве в словарь типа добавляется запись (см. tp_dict ниже), содержащая дескриптор метода.

Наследование:

Это поле не наследуется подтипами (методы наследуются через другой механизм).

struct PyMemberDef *PyTypeObject.tp_members

Необязательный указатель на статический массив PyMemberDef структур, завершающийся NULL, объявляющий обычные элементы данных (поля или слоты) экземпляров этого типа.

Для каждой записи в массиве в словарь типа добавляется запись, содержащая дескриптор члена (см. tp_dict ниже).

Наследование:

Это поле не наследуется подтипами (члены наследуются через другой механизм).

struct PyGetSetDef *PyTypeObject.tp_getset

Необязательный указатель на статический массив PyGetSetDef структур, завершающийся NULL, объявляющий вычисляемые атрибуты экземпляров этого типа.

Для каждой записи в массиве в словарь типа добавляется запись, содержащая дескриптор getset (см. tp_dict ниже).

Наследование:

Это поле не наследуется подтипами (вычисляемые атрибуты наследуются через другой механизм).

PyTypeObject *PyTypeObject.tp_base

Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа вызовом метатипа.

Примечание

Инициализация слотов подчиняется правилам инициализации глобальных переменных. C99 требует, чтобы инициализаторы были «адресными константами». Обозначения функций, такие как PyType_GenericNew(), с неявным преобразованием в указатель, являются допустимыми адресными константами C99.

Однако унарный оператор '&', применённый к нестатической переменной, такой как PyBaseObject_Type, не обязан давать адресную константу. Компиляторы могут это поддерживать (gcc поддерживает), MSVC – нет. Оба компилятора в этом конкретном поведении строго соответствуют стандарту.

Следовательно, tp_base должно устанавливаться в функции инициализации модуля расширения.

Наследование:

Это поле не наследуется подтипами (очевидно).

По умолчанию:

По умолчанию это поле равно &PyBaseObject_Type (которое программистам Python известно как тип object).

PyObject *PyTypeObject.tp_dict

Словарь типа сохраняется здесь с помощью PyType_Ready().

Обычно это поле должно быть инициализировано значением NULL перед вызовом PyType_Ready; оно также может быть инициализировано словарём, содержащим начальные атрибуты типа. После того как PyType_Ready() инициализировал тип, в этот словарь можно добавлять дополнительные атрибуты только в том случае, если они не соответствуют перегруженным операциям (например, __add__()). После завершения инициализации типа это поле должно считаться доступным только для чтения.

Некоторые типы могут не хранить свой словарь в этом слоте. Используйте PyType_GetDict() для получения словаря для произвольного типа.

Изменено в версии 3.12: Детали реализации: для статических встроенных типов это всегда NULL. Вместо этого словарь для таких типов хранится в PyInterpreterState. Используйте PyType_GetDict() для получения словаря для произвольного типа.

Наследование:

Это поле не наследуется подтипами (хотя определённые здесь атрибуты наследуются через другой механизм).

По умолчанию:

Если это поле равно NULL, PyType_Ready() назначит ему новый словарь.

Предупреждение

Небезопасно использовать PyDict_SetItem() на или иным образом изменять tp_dict с помощью C-API словаря.

descrgetfunc PyTypeObject.tp_descr_get

Необязательный указатель на функцию «descriptor get».

Сигнатура функции:

PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);

Наследование:

Это поле наследуется подтипами.

descrsetfunc PyTypeObject.tp_descr_set

Необязательный указатель на функцию для установки и удаления значения дескриптора.

Сигнатура функции:

int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);

Аргумент value устанавливается в NULL для удаления значения.

Наследование:

Это поле наследуется подтипами.

Py_ssize_t PyTypeObject.tp_dictoffset

Хотя это поле всё ещё поддерживается, следует использовать Py_TPFLAGS_MANAGED_DICT вместо него, если это возможно.

Если экземпляры этого типа имеют словарь, содержащий переменные экземпляра, это поле не равно нулю и содержит смещение в структуре экземпляра для словаря переменных экземпляра; это смещение используется PyObject_GenericGetAttr().

Не путайте это поле с tp_dict; это словарь для атрибутов самого объекта типа.

Значение задаёт смещение словаря относительно начала структуры экземпляра.

tp_dictoffset следует рассматривать как доступный только для записи. Чтобы получить указатель на словарь, вызовите PyObject_GenericGetDict(). Вызов PyObject_GenericGetDict() может потребовать выделения памяти для словаря, поэтому может быть эффективнее вызвать PyObject_GetAttr() при доступе к атрибуту объекта.

Установка обоих битов Py_TPFLAGS_MANAGED_DICT и tp_dictoffset является ошибкой.

Наследование:

Это поле наследуется подтипами. Подтип не должен переопределять это смещение; это может быть небезопасно, если код C попытается получить доступ к словарю по предыдущему смещению. Для корректной поддержки наследования используйте Py_TPFLAGS_MANAGED_DICT.

По умолчанию:

Этот слот не имеет значения по умолчанию. Для статических типов, если поле равно NULL, то для экземпляров не создаётся __dict__.

Если в поле tp_dict установлен бит Py_TPFLAGS_MANAGED_DICT, то tp_dictoffset будет установлено в -1, чтобы указать, что использовать это поле небезопасно.

initproc PyTypeObject.tp_init

Необязательный указатель на функцию инициализации экземпляра.

Эта функция соответствует методу __init__() классов. Как и __init__(), можно создать экземпляр без вызова __init__(), и можно переинициализировать экземпляр, вызвав его метод __init__() ещё раз.

Сигнатура функции:

int tp_init(PyObject *self, PyObject *args, PyObject *kwds);

Аргумент self – это инициализируемый экземпляр; аргументы args и kwds представляют позиционные и именованные аргументы вызова __init__().

Функция tp_init, если она не NULL, вызывается при обычном создании экземпляра через вызов его типа, после того как функция tp_new типа вернула экземпляр этого типа. Если функция tp_new возвращает экземпляр другого типа, не являющегося подтипом исходного, функция tp_init не вызывается; если tp_new возвращает экземпляр подтипа исходного типа, вызывается tp_init подтипа.

Возвращает 0 при успехе, -1 и устанавливает исключение при ошибке.

Наследование:

Это поле наследуется подтипами.

По умолчанию:

Для статических типов это поле не имеет значения по умолчанию.

allocfunc PyTypeObject.tp_alloc

Необязательный указатель на функцию выделения экземпляра.

Сигнатура функции:

PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);

Наследование:

Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными с помощью инструкции class).

По умолчанию:

Для динамических подтипов это поле всегда устанавливается в PyType_GenericAlloc(), чтобы принудительно применять стандартную стратегию выделения памяти из кучи.

Для статических подтипов PyBaseObject_Type использует PyType_GenericAlloc(). Это рекомендуемое значение для всех статически определённых типов.

newfunc PyTypeObject.tp_new

Необязательный указатель на функцию создания экземпляра.

Сигнатура функции:

PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);

Аргумент subtype – это тип создаваемого объекта; аргументы args и kwds представляют позиционные и ключевые аргументы вызова типа. Обратите внимание, что subtype не обязан совпадать с типом, чья функция tp_new вызывается; это может быть подтип этого типа (но не произвольный тип).

Функция tp_new должна вызывать subtype->tp_alloc(subtype, nitems) для выделения памяти под объект, а затем выполнять лишь минимально необходимую инициализацию. Инициализацию, которую можно безопасно пропустить или повторить, следует помещать в обработчик tp_init. Хорошее эмпирическое правило: для неизменяемых типов вся инициализация должна выполняться в tp_new, а для изменяемых типов большую часть инициализации лучше отложить до tp_init.

Флаг Py_TPFLAGS_DISALLOW_INSTANTIATION используется для запрета создания экземпляров типа в Python.

Наследование:

Это поле наследуется подтипами, за исключением статических типов, у которых tp_base равно NULL или &PyBaseObject_Type.

По умолчанию:

Для статических типов это поле не имеет значения по умолчанию. Это означает, что если слот определён как NULL, тип нельзя вызвать для создания новых экземпляров; предположительно, существует другой способ создания экземпляров, например фабричная функция.

freefunc PyTypeObject.tp_free

Необязательный указатель на функцию освобождения экземпляра. Её сигнатура:

void tp_free(void *self);

Инициализатор, совместимый с этой сигнатурой: PyObject_Free().

Наследование:

Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными через объявление класса).

По умолчанию:

В динамических подтипах это поле устанавливается в деаллокатор, подходящий для соответствия PyType_GenericAlloc() и значению флага Py_TPFLAGS_HAVE_GC.

Для статических подтипов PyBaseObject_Type использует PyObject_Del().

inquiry PyTypeObject.tp_is_gc

Необязательный указатель на функцию, вызываемую сборщиком мусора.

Сборщику мусора необходимо знать, можно ли собрать конкретный объект или нет. Обычно достаточно посмотреть на поле tp_flags типа объекта и проверить бит флага Py_TPFLAGS_HAVE_GC. Но некоторые типы содержат как статически, так и динамически выделенные экземпляры, и статически выделенные экземпляры не подлежат сборке. Такие типы должны определять эту функцию; она должна возвращать 1 для собираемого экземпляра и 0 для несобираемого. Сигнатура:

int tp_is_gc(PyObject *self);

(Единственный пример этого – сами типы. Метакласс, PyType_Type, определяет эту функцию, чтобы различать статически и динамически выделенные типы.)

Наследование:

Это поле наследуется подтипами.

По умолчанию:

У этого слота нет значения по умолчанию. Если это поле равно NULL, то в качестве функционального эквивалента используется Py_TPFLAGS_HAVE_GC.

PyObject *PyTypeObject.tp_bases

Кортеж базовых типов.

Это поле должно быть установлено в NULL и считаться доступным только для чтения. Python заполнит его, когда тип будет initialized.

Для динамически создаваемых классов вместо аргумента bases из PyType_FromSpecWithBases() можно использовать Py_tp_bases slot. Предпочтительна форма с аргументом.

Предупреждение

Множественное наследование плохо работает для статически определённых типов. Если установить tp_bases в кортеж, Python не вызовет ошибку, но некоторые слоты будут унаследованы только от первого базового класса.

Наследование:

Это поле не наследуется.

PyObject *PyTypeObject.tp_mro

Кортеж, содержащий расширенный набор базовых типов, начиная с самого типа и заканчивая object, в порядке разрешения методов (MRO).

Это поле должно быть установлено в NULL и считаться доступным только для чтения. Python заполнит его, когда тип будет initialized.

Наследование:

Это поле не наследуется; оно вычисляется заново с помощью PyType_Ready().

PyObject *PyTypeObject.tp_cache

Не используется. Только для внутреннего использования.

Наследование:

Это поле не наследуется.

void *PyTypeObject.tp_subclasses

Коллекция подклассов. Только для внутреннего использования. Может быть недопустимым указателем.

Чтобы получить список подклассов, вызовите метод Python __subclasses__().

Изменено в версии 3.12: Для некоторых типов это поле не содержит допустимый PyObject*. Тип был изменён на void*, чтобы указать на это.

Наследование:

Это поле не наследуется.

PyObject *PyTypeObject.tp_weaklist

Голова списка слабых ссылок для слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего использования.

Изменено в версии 3.12: Деталь внутренней реализации: для статических встроенных типов это всегда NULL, даже если добавлены слабые ссылки. Вместо этого слабые ссылки для каждого хранятся в PyInterpreterState. Используйте публичный C-API или внутренний макрос _PyObject_GET_WEAKREFS_LISTPTR(), чтобы избежать этого различия.

Наследование:

Это поле не наследуется.

destructor PyTypeObject.tp_del

Это поле устарело. Используйте tp_finalize вместо него.

unsigned int PyTypeObject.tp_version_tag

Используется для индексации кэша методов. Только для внутреннего использования.

Наследование:

Это поле не наследуется.

destructor PyTypeObject.tp_finalize

Необязательный указатель на функцию финализации экземпляра. Её сигнатура:

void tp_finalize(PyObject *self);

Если tp_finalize установлен, интерпретатор вызывает его один раз при финализации экземпляра. Он вызывается либо сборщиком мусора (если экземпляр является частью изолированного цикла ссылок), либо непосредственно перед освобождением объекта. В любом случае гарантируется, что он будет вызван до попытки разорвать циклы ссылок, что обеспечивает нахождение объекта в корректном состоянии.

tp_finalize не должен изменять текущий статус исключения; поэтому рекомендуемый способ написания нетривиального финализатора:

static void
local_finalize(PyObject *self)
{
    PyObject *error_type, *error_value, *error_traceback;

    /* Сохранить текущее исключение, если оно есть. */
    PyErr_Fetch(&error_type, &error_value, &error_traceback);

    /* ... */

    /* Восстановить сохранённое исключение. */
    PyErr_Restore(error_type, error_value, error_traceback);
}

Наследование:

Это поле наследуется подтипами.

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

Изменено в версии 3.8: До версии 3.8 необходимо было установить бит флагов Py_TPFLAGS_HAVE_FINALIZE, чтобы это поле можно было использовать. Теперь это не требуется.

См. также

«Безопасная финализация объектов» (PEP 442)

vectorcallfunc PyTypeObject.tp_vectorcall

Функция vectorcall, используемая для вызовов этого объекта типа. Другими словами, она используется для реализации vectorcall для type.__call__. Если tp_vectorcall равно NULL, используется реализация вызова по умолчанию с использованием __new__() и __init__().

Наследование:

Это поле никогда не наследуется.

Добавлено в версии 3.9: (поле существует с версии 3.8, но используется только с версии 3.9)

unsigned char PyTypeObject.tp_watched

Внутреннее. Не использовать.

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

Статические типыStatic Types

Традиционно типы, определяемые в коде C, являются статическими, то есть статическая структура PyTypeObject определяется непосредственно в коде и инициализируется с помощью PyType_Ready().

В результате получаются типы, которые ограничены по сравнению с типами, определёнными в Python.

  • Статические типы ограничены одним базовым классом, то есть не могут использовать множественное наследование.

  • Объекты статических типов (но не обязательно их экземпляры) неизменяемы. Из Python невозможно добавить или изменить атрибуты объекта типа.

  • Объекты статических типов разделяются между под-интерпретаторами, поэтому они не должны содержать состояние, специфичное для под-интерпретатора.

Кроме того, поскольку PyTypeObject является лишь частью Limited API в виде непрозрачной структуры, любые модули расширения, использующие статические типы, должны быть скомпилированы для конкретной минорной версии Python.

Кучные типыHeap Types

Альтернативой статическим типам являются кучные типы (heap-allocated types), или кучные типы (heap types) для краткости. Они очень похожи на классы, создаваемые с помощью оператора class. У кучных типов установлен флаг Py_TPFLAGS_HEAPTYPE.

Для этого заполняется структура PyType_Spec и вызывается PyType_FromSpec(), PyType_FromSpecWithBases(), PyType_FromModuleAndSpec() или PyType_FromMetaclass().

Структуры числовых объектовNumber Object Structures

type PyNumberMethods

Эта структура содержит указатели на функции, которые объект использует для реализации числового протокола. Каждая функция используется одноимённой функцией, описанной в разделе Числовой протокол.

Вот определение структуры:

typedef struct {
     binaryfunc nb_add;
     binaryfunc nb_subtract;
     binaryfunc nb_multiply;
     binaryfunc nb_remainder;
     binaryfunc nb_divmod;
     ternaryfunc nb_power;
     unaryfunc nb_negative;
     unaryfunc nb_positive;
     unaryfunc nb_absolute;
     inquiry nb_bool;
     unaryfunc nb_invert;
     binaryfunc nb_lshift;
     binaryfunc nb_rshift;
     binaryfunc nb_and;
     binaryfunc nb_xor;
     binaryfunc nb_or;
     unaryfunc nb_int;
     void *nb_reserved;
     unaryfunc nb_float;

     binaryfunc nb_inplace_add;
     binaryfunc nb_inplace_subtract;
     binaryfunc nb_inplace_multiply;
     binaryfunc nb_inplace_remainder;
     ternaryfunc nb_inplace_power;
     binaryfunc nb_inplace_lshift;
     binaryfunc nb_inplace_rshift;
     binaryfunc nb_inplace_and;
     binaryfunc nb_inplace_xor;
     binaryfunc nb_inplace_or;

     binaryfunc nb_floor_divide;
     binaryfunc nb_true_divide;
     binaryfunc nb_inplace_floor_divide;
     binaryfunc nb_inplace_true_divide;

     unaryfunc nb_index;

     binaryfunc nb_matrix_multiply;
     binaryfunc nb_inplace_matrix_multiply;
} PyNumberMethods;

Примечание

Бинарные и тернарные функции должны проверять тип всех своих операндов и выполнять необходимые преобразования (хотя бы один из операндов должен быть экземпляром определяемого типа). Если операция не определена для данных операндов, бинарные и тернарные функции должны вернуть Py_NotImplemented; если произошла другая ошибка, они должны вернуть NULL и установить исключение.

Примечание

Поле nb_reserved всегда должно быть NULL. Ранее оно называлось nb_long и было переименовано в Python 3.0.1.

binaryfunc PyNumberMethods.nb_add
binaryfunc PyNumberMethods.nb_subtract
binaryfunc PyNumberMethods.nb_multiply
binaryfunc PyNumberMethods.nb_remainder
binaryfunc PyNumberMethods.nb_divmod
ternaryfunc PyNumberMethods.nb_power
unaryfunc PyNumberMethods.nb_negative
unaryfunc PyNumberMethods.nb_positive
unaryfunc PyNumberMethods.nb_absolute
inquiry PyNumberMethods.nb_bool
unaryfunc PyNumberMethods.nb_invert
binaryfunc PyNumberMethods.nb_lshift
binaryfunc PyNumberMethods.nb_rshift
binaryfunc PyNumberMethods.nb_and
binaryfunc PyNumberMethods.nb_xor
binaryfunc PyNumberMethods.nb_or
unaryfunc PyNumberMethods.nb_int
void *PyNumberMethods.nb_reserved
unaryfunc PyNumberMethods.nb_float
binaryfunc PyNumberMethods.nb_inplace_add
binaryfunc PyNumberMethods.nb_inplace_subtract
binaryfunc PyNumberMethods.nb_inplace_multiply
binaryfunc PyNumberMethods.nb_inplace_remainder
ternaryfunc PyNumberMethods.nb_inplace_power
binaryfunc PyNumberMethods.nb_inplace_lshift
binaryfunc PyNumberMethods.nb_inplace_rshift
binaryfunc PyNumberMethods.nb_inplace_and
binaryfunc PyNumberMethods.nb_inplace_xor
binaryfunc PyNumberMethods.nb_inplace_or
binaryfunc PyNumberMethods.nb_floor_divide
binaryfunc PyNumberMethods.nb_true_divide
binaryfunc PyNumberMethods.nb_inplace_floor_divide
binaryfunc PyNumberMethods.nb_inplace_true_divide
unaryfunc PyNumberMethods.nb_index
binaryfunc PyNumberMethods.nb_matrix_multiply
binaryfunc PyNumberMethods.nb_inplace_matrix_multiply

Структуры объектов отображенияMapping Object Structures

type PyMappingMethods

Эта структура хранит указатели на функции, которые объект использует для реализации протокола отображения. Она содержит три члена:

lenfunc PyMappingMethods.mp_length

Эта функция используется PyMapping_Size() и PyObject_Size() и имеет ту же сигнатуру. Этот слот может быть установлен в NULL, если у объекта нет определённой длины.

binaryfunc PyMappingMethods.mp_subscript

Эта функция используется PyObject_GetItem() и PySequence_GetSlice() и имеет ту же сигнатуру, что и PyObject_GetItem(). Этот слот должен быть заполнен, чтобы функция PyMapping_Check() возвращала 1; в противном случае он может быть NULL .

objobjargproc PyMappingMethods.mp_ass_subscript

Эта функция используется PyObject_SetItem(), PyObject_DelItem(), PySequence_SetSlice() и PySequence_DelSlice(). У неё та же сигнатура, что и у PyObject_SetItem(), но v также может быть установлен в NULL для удаления элемента. Если этот слот равен NULL, объект не поддерживает присваивание и удаление элементов.

Структуры объектов последовательностейSequence Object Structures

type PySequenceMethods

Эта структура содержит указатели на функции, которые объект использует для реализации протокола последовательности.

lenfunc PySequenceMethods.sq_length

Эта функция используется PySequence_Size() и PyObject_Size() и имеет ту же сигнатуру. Она также используется для обработки отрицательных индексов через слоты sq_item и sq_ass_item.

binaryfunc PySequenceMethods.sq_concat

Эта функция используется PySequence_Concat() и имеет ту же сигнатуру. Она также используется оператором + после попытки численного сложения через слот nb_add.

ssizeargfunc PySequenceMethods.sq_repeat

Эта функция используется PySequence_Repeat() и имеет ту же сигнатуру. Она также используется оператором * после попытки численного умножения через слот nb_multiply.

ssizeargfunc PySequenceMethods.sq_item

Эта функция используется PySequence_GetItem() и имеет ту же сигнатуру. Она также используется PyObject_GetItem() после попытки индексирования через слот mp_subscript. Этот слот должен быть заполнен, чтобы функция PySequence_Check() возвращала 1; в противном случае он может быть NULL.

Отрицательные индексы обрабатываются следующим образом: если слот sq_length заполнен, он вызывается, и длина последовательности используется для вычисления положительного индекса, который передаётся sq_item. Если sq_length равно NULL, индекс передаётся функции как есть.

ssizeobjargproc PySequenceMethods.sq_ass_item

Эта функция используется PySequence_SetItem() и имеет ту же сигнатуру. Она также используется PyObject_SetItem() и PyObject_DelItem() после попытки присваивания и удаления элемента через слот mp_ass_subscript. Этот слот может быть оставлен равным NULL, если объект не поддерживает присваивание и удаление элементов.

objobjproc PySequenceMethods.sq_contains

Эта функция может использоваться PySequence_Contains() и имеет ту же сигнатуру. Этот слот может быть оставлен равным NULL; в этом случае PySequence_Contains() просто проходит по последовательности, пока не найдёт совпадение.

binaryfunc PySequenceMethods.sq_inplace_concat

Эта функция используется PySequence_InPlaceConcat() и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его. Этот слот может быть оставлен равным NULL; в этом случае PySequence_InPlaceConcat() будет использовать PySequence_Concat() как запасной вариант. Она также используется расширенным присваиванием += после попытки численного сложения на месте через слот nb_inplace_add.

ssizeargfunc PySequenceMethods.sq_inplace_repeat

Эта функция используется PySequence_InPlaceRepeat() и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его. Этот слот может быть оставлен равным NULL; в этом случае PySequence_InPlaceRepeat() будет использовать PySequence_Repeat() как запасной вариант. Она также используется расширенным присваиванием *= после попытки численного умножения на месте через слот nb_inplace_multiply.

Структуры объектов буфераBuffer Object Structures

type PyBufferProcs

Эта структура содержит указатели на функции, необходимые для протокола буфера. Протокол определяет, как объект-экспортёр может предоставлять свои внутренние данные объектам-потребителям.

getbufferproc PyBufferProcs.bf_getbuffer

Сигнатура этой функции:

int (PyObject *exporter, Py_buffer *view, int flags);

Обрабатывает запрос к экспортёру на заполнение представления в соответствии с флагами. За исключением пункта (3), реализация этой функции ОБЯЗАНА выполнить следующие шаги:

  1. Проверить, может ли быть удовлетворён запрос. Если нет – вызвать BufferError, установить view->obj в NULL и вернуть -1.

  2. Заполнить запрошенные поля.

  3. Увеличить внутренний счётчик числа экспортов.

  4. Установить view->obj в exporter и увеличить view->obj.

  5. Вернуть 0.

Если экспортёр является частью цепочки или дерева поставщиков буферов, можно использовать две основные схемы:

  • Ре-экспорт: каждый элемент дерева выступает в роли экспортирующего объекта и устанавливает view->obj в новую ссылку на самого себя.

  • Перенаправление: запрос буфера перенаправляется на корневой объект дерева. Здесь view->obj будет новой ссылкой на корневой объект.

Отдельные поля представления описаны в разделе Структура буфера, правила, как экспортёр должен реагировать на конкретные запросы – в разделе Типы запросов буфера.

Вся память, на которую указывает структура Py_buffer, принадлежит экспортёру и должна оставаться действительной, пока есть хотя бы один потребитель. format, shape, strides, suboffsets и internal доступны потребителю только для чтения.

PyBuffer_FillInfo() предоставляет простой способ предоставления простого байтового буфера, корректно обрабатывая все типы запросов.

PyObject_GetBuffer() – это интерфейс для потребителя, который оборачивает эту функцию.

releasebufferproc PyBufferProcs.bf_releasebuffer

Сигнатура этой функции:

void (PyObject *exporter, Py_buffer *view);

Обрабатывает запрос на освобождение ресурсов буфера. Если никакие ресурсы освобождать не нужно, PyBufferProcs.bf_releasebuffer может быть NULL. В противном случае стандартная реализация этой функции выполнит следующие необязательные шаги:

  1. Уменьшить внутренний счётчик числа экспортов.

  2. Если счётчик равен 0, освободить всю память, связанную с представлением.

Экспортёр ОБЯЗАН использовать поле internal для отслеживания ресурсов, специфичных для буфера. Гарантируется, что это поле остаётся постоянным, в то время как потребитель МОЖЕТ передавать копию исходного буфера в качестве аргумента view.

Эта функция НЕ ДОЛЖНА уменьшать счётчик view->obj, поскольку это делается автоматически в PyBuffer_Release() (такая схема полезна для разрыва циклических ссылок).

PyBuffer_Release() – это интерфейс для потребителя, который оборачивает эту функцию.

Асинхронные структуры объектовAsync Object Structures

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

type PyAsyncMethods

Эта структура содержит указатели на функции, необходимые для реализации объектов ожидаемый объект и асинхронный итератор.

Вот определение структуры:

typedef struct {
    unaryfunc am_await;
    unaryfunc am_aiter;
    unaryfunc am_anext;
    sendfunc am_send;
} PyAsyncMethods;
unaryfunc PyAsyncMethods.am_await

Сигнатура этой функции:

PyObject *am_await(PyObject *self);

Возвращаемый объект должен быть итератором, т.е. PyIter_Check() должен возвращать 1 для него.

Этот слот может быть установлен в NULL, если объект не является ожидаемым объектом.

unaryfunc PyAsyncMethods.am_aiter

Сигнатура этой функции:

PyObject *am_aiter(PyObject *self);

Должен возвращать объект асинхронный итератор. Подробнее см. __anext__().

Этот слот может быть установлен в NULL, если объект не реализует протокол асинхронной итерации.

unaryfunc PyAsyncMethods.am_anext

Сигнатура этой функции:

PyObject *am_anext(PyObject *self);

Должен возвращать объект ожидаемый объект. Подробнее см. __anext__(). Этот слот может быть установлен в NULL.

sendfunc PyAsyncMethods.am_send

Сигнатура этой функции:

PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);

Подробнее см. PyIter_Send(). Этот слот может быть установлен в NULL.

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

Определения типов слотовSlot Type typedefs

typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Часть Stable ABI.

Назначение этой функции – разделить выделение памяти и её инициализацию. Она должна возвращать указатель на блок памяти достаточной длины для экземпляра, с подходящим выравниванием и обнулённый, но с ob_refcnt, установленным в 1, и ob_type, установленным в аргумент типа. Если tp_itemsize типа не равно нулю, поле ob_size объекта должно быть инициализировано значением nitems, а длина выделенного блока памяти должна быть tp_basicsize + nitems*tp_itemsize, округлённой до кратного sizeof(void*); в противном случае nitems не используется, и длина блока должна быть tp_basicsize.

Эта функция не должна выполнять никакой другой инициализации экземпляра, включая выделение дополнительной памяти; это должно выполнять tp_new.

typedef void (*destructor)(PyObject*)
Часть Stable ABI.
typedef void (*freefunc)(void*)

См. tp_free.

typedef PyObject *(*newfunc)(PyTypeObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_new.

typedef int (*initproc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Часть Stable ABI.

См. tp_repr.

typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)
Часть Stable ABI.

Возвращает значение именованного атрибута для объекта.

typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)
Часть Stable ABI.

Устанавливает значение именованного атрибута для объекта. Аргумент value устанавливается в NULL для удаления атрибута.

typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)
Часть Stable ABI.

Возвращает значение именованного атрибута для объекта.

См. tp_getattro.

typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)
Часть Stable ABI.

Устанавливает значение именованного атрибута для объекта. Аргумент value устанавливается в NULL для удаления атрибута.

См. tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_descr_get.

typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Часть Stable ABI.

См. tp_hash.

typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)
Часть Stable ABI.

См. tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Часть Stable ABI.

См. tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Часть Stable ABI.

См. tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Часть Stable ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
Часть Stable ABI начиная с версии 3.12.
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
Часть Stable ABI начиная с версии 3.12.
typedef PyObject *(*unaryfunc)(PyObject*)
Часть Stable ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Часть Stable ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

См. am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Часть Stable ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)
Часть Stable ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Часть Stable ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

ПримерыExamples

Ниже приведены простые примеры определений типов Python. Они включают распространённые варианты использования, с которыми можно столкнуться. Некоторые демонстрируют сложные граничные случаи. За дополнительными примерами, практической информацией и учебным пособием обращайтесь к Defining Extension Types: Tutorial и Defining Extension Types: Assorted Topics.

Базовый статический тип:

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_new = myobj_new,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
};

Также можно встретить старый код (особенно в кодовой базе CPython) с более многословным инициализатором:

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "mymod.MyObject",               /* tp_name */
    sizeof(MyObject),               /* tp_basicsize */
    0,                              /* tp_itemsize */
    (destructor)myobj_dealloc,      /* tp_dealloc */
    0,                              /* tp_vectorcall_offset */
    0,                              /* tp_getattr */
    0,                              /* tp_setattr */
    0,                              /* tp_as_async */
    (reprfunc)myobj_repr,           /* tp_repr */
    0,                              /* tp_as_number */
    0,                              /* tp_as_sequence */
    0,                              /* tp_as_mapping */
    0,                              /* tp_hash */
    0,                              /* tp_call */
    0,                              /* tp_str */
    0,                              /* tp_getattro */
    0,                              /* tp_setattro */
    0,                              /* tp_as_buffer */
    0,                              /* tp_flags */
    PyDoc_STR("My objects"),        /* tp_doc */
    0,                              /* tp_traverse */
    0,                              /* tp_clear */
    0,                              /* tp_richcompare */
    0,                              /* tp_weaklistoffset */
    0,                              /* tp_iter */
    0,                              /* tp_iternext */
    0,                              /* tp_methods */
    0,                              /* tp_members */
    0,                              /* tp_getset */
    0,                              /* tp_base */
    0,                              /* tp_dict */
    0,                              /* tp_descr_get */
    0,                              /* tp_descr_set */
    0,                              /* tp_dictoffset */
    0,                              /* tp_init */
    0,                              /* tp_alloc */
    myobj_new,                      /* tp_new */
};

Тип, поддерживающий слабые ссылки, словари экземпляров и хеширование:

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
         Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
         Py_TPFLAGS_MANAGED_WEAKREF,
    .tp_new = myobj_new,
    .tp_traverse = (traverseproc)myobj_traverse,
    .tp_clear = (inquiry)myobj_clear,
    .tp_alloc = PyType_GenericNew,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
    .tp_hash = (hashfunc)myobj_hash,
    .tp_richcompare = PyBaseObject_Type.tp_richcompare,
};

Подкласс str, который нельзя наследовать и который нельзя вызывать для создания экземпляров (например, используется отдельная фабричная функция) с помощью флага Py_TPFLAGS_DISALLOW_INSTANTIATION:

typedef struct {
    PyUnicodeObject raw;
    char *extra;
} MyStr;

static PyTypeObject MyStr_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyStr",
    .tp_basicsize = sizeof(MyStr),
    .tp_base = NULL,  // устанавливается в &PyUnicode_Type при инициализации модуля
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

Простейший статический тип с экземплярами фиксированной длины:

typedef struct {
    PyObject_HEAD
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
};

Простейший статический тип с экземплярами переменной длины:

typedef struct {
    PyObject_VAR_HEAD
    const char *data[1];
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject) - sizeof(char *),
    .tp_itemsize = sizeof(char *),
};