Типовые объекты

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

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

В дополнение к приведенному ниже краткому справочнику, раздел Примеры содержит краткое описание значения и использования PyTypeObject.

Краткая справка

«tp slots»

PyTypeObject Slot [1]

Type

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

Информация [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

беззнаковая длина

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 *

__база__

X

tp_dict

PyObject *

__дикт__.

?

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 *

__базы__

~

<tp_mro>

PyObject *

__mro__

~

[tp_cache]

PyObject *

[tp_subclasses]

void *

__подклассы__

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

__del__

X

tp_vectorcall

vectorcallfunc

[tp_watched]

беззнаковый символ

субслоты

Слот

Type

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

am_await

unaryfunc

__ожидание__

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

__мул__ __рмул__

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

__rrshift__ __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

__содержит__

sq_inplace_concat

binaryfunc

__iadd__

sq_inplace_repeat

ssizeargfunc

__imul__

bf_getbuffer

getbufferproc()

bf_releasebuffer

releasebufferproc()

Типефики слотов

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

Подробнее см. в разделе Типефикаторы типов слотов ниже.

Определение PyTypeObject

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

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    Py_ssize_t tp_vectorcall_offset;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
                                    or tp_reserved (Python 3) */
    reprfunc tp_repr;

    /* Method suites for standard classes */

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

    /* More standard operations (here for binary compatibility) */

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

    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    unsigned long tp_flags;

    const char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    Py_ssize_t tp_weaklistoffset;

    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Attribute descriptor and subclassing stuff */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    // Strong reference on a heap type, borrowed reference on a static type
    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; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

    /* Type attribute cache version tag. Added in version 2.6 */
    unsigned int tp_version_tag;

    destructor tp_finalize;
    vectorcallfunc tp_vectorcall;

    /* bitset of which type-watchers care about this type */
    unsigned char tp_watched;
} PyTypeObject;

Слоты PyObject

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

Py_ssize_t PyObject.ob_refcnt
Часть Стабильный ABI.

Это количество ссылок на объект типа, инициализированное макросом PyObject_HEAD_INIT в значение 1. Обратите внимание, что для statically allocated type objects экземпляры типа (объекты, чей ob_type указывает обратно на тип) не считаются ссылками. Но для dynamically allocated type objects экземпляры до считаются ссылками.

** Наследство:**

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

PyTypeObject *PyObject.ob_type
Часть Стабильный 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() не изменяет это поле, если оно ненулевое.

** Наследство:**

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

Слоты PyVarObject

Py_ssize_t PyVarObject.ob_size
Часть Стабильный ABI.

Для statically allocated type objects оно должно быть инициализировано нулем. Для dynamically allocated type objects это поле имеет специальное внутреннее значение.

** Наследство:**

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

Слоты для объектов PyTypeObject

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

const char *PyTypeObject.tp_name

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

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

Для statically allocated type objects поле tp_name должно содержать точку. Все, что до последней точки, становится доступным как атрибут __module__, а все, что после последней точки, становится доступным как атрибут __name__.

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

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

** Наследство:**

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

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

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

Существует два вида типов: типы с экземплярами фиксированной длины имеют нулевое поле tp_itemsize, а типы с экземплярами переменной длины - ненулевое поле tp_itemsize. Для типа с экземплярами фиксированной длины все экземпляры имеют одинаковый размер, заданный в tp_basicsize.

Для типа с экземплярами переменной длины экземпляр должен иметь поле ob_size, а размер экземпляра равен tp_basicsize плюс N раз tp_itemsize, где N - «длина» объекта. Значение N обычно хранится в поле ob_size экземпляра. Существуют исключения: например, в ints для обозначения отрицательного числа используется отрицательный ob_size, и N там равно abs(ob_size). Кроме того, наличие поля ob_size в схеме экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура для типа list имеет экземпляры фиксированной длины, но эти экземпляры имеют значимое поле ob_size).

Базовый размер включает поля экземпляра, объявленные макросом PyObject_HEAD или PyObject_VAR_HEAD (в зависимости от того, какой из них используется для объявления структуры экземпляра), а она, в свою очередь, включает поля _ob_prev и _ob_next, если они присутствуют. Это означает, что единственный правильный способ получить инициализатор для tp_basicsize - использовать оператор sizeof на структуре, используемой для объявления макета экземпляра. Базовый размер не включает в себя размер заголовка GC.

Замечание о выравнивании: если элементы переменной требуют определенного выравнивания, об этом должно позаботиться значение tp_basicsize. Пример: предположим, что тип реализует массив double. tp_itemsize - sizeof(double). Программист отвечает за то, чтобы tp_basicsize был кратен sizeof(double) (предполагается, что это требование выравнивания для double).

Для любого типа с экземплярами переменной длины это поле не должно быть NULL.

** Наследство:**

Эти поля наследуются подтипами отдельно. Если базовый тип имеет ненулевое значение 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);
    // free references and buffers here
    tp->tp_free(self);
    Py_DECREF(tp);
}

** Наследство:**

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

Py_ssize_t PyTypeObject.tp_vectorcall_offset

Необязательное смещение к функции для каждого экземпляра, которая реализует вызов объекта с помощью vectorcall protocol, более эффективной альтернативы более простому 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 не рекомендовалось использовать mutable heap types для реализации протокола 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

Необязательный указатель на функцию get-attribute-string.

Это поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция 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

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

Added in version 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.

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

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

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

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

Сигнатура такая же, как и для 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

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

** Наследство:**

Поле 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 его экземпляров считается ссылкой на тип, и объект типа увеличивается при создании нового экземпляра и уменьшается при уничтожении экземпляра (это не относится к экземплярам подтипов; только тип, на который ссылается ob_type экземпляра, получает INCREF’ed или DECREF’ed). Типы кучи также должны support garbage collection, поскольку они могут образовывать цикл ссылок со своим собственным объектом модуля.

** Наследство:**

???

Py_TPFLAGS_BASETYPE

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

** Наследство:**

???

Py_TPFLAGS_READY

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

** Наследство:**

???

Py_TPFLAGS_READYING

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

** Наследство:**

???

Py_TPFLAGS_HAVE_GC

Этот бит устанавливается, если объект поддерживает сборку мусора. Если этот бит установлен, экземпляры должны создаваться с помощью PyObject_GC_New и уничтожаться с помощью PyObject_GC_Del(). Более подробная информация приведена в разделе Поддержка циклической сборки мусора. Этот бит также означает, что в объекте типа присутствуют связанные с GC поля 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.

Added in version 3.8.

** Наследство:**

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

Py_TPFLAGS_MANAGED_DICT

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

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

Функция обхода типа должна вызывать PyObject_VisitManagedDict(), а ее функция очистки - PyObject_ClearManagedDict().

Added in version 3.12.

** Наследство:**

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

Py_TPFLAGS_MANAGED_WEAKREF

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

Added in version 3.12.

** Наследство:**

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

Py_TPFLAGS_ITEMS_AT_END

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

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

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

Added in version 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

Эти флаги используются такими функциями, как PyLong_Check(), чтобы быстро определить, является ли тип подклассом встроенного типа; такие специфические проверки быстрее, чем общие проверки, например PyObject_IsInstance(). Для пользовательских типов, наследующих от встроенных, следует соответствующим образом устанавливать tp_flags, иначе код, взаимодействующий с такими типами, будет вести себя по-разному в зависимости от того, какой тип проверки используется.

Py_TPFLAGS_HAVE_FINALIZE

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

Added in version 3.4.

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

Py_TPFLAGS_HAVE_VECTORCALL

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

** Наследство:**

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

Added in version 3.9.

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

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

Py_TPFLAGS_IMMUTABLETYPE

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

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

** Наследство:**

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

Added in version 3.10.

Py_TPFLAGS_DISALLOW_INSTANTIATION

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

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

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

** Наследство:**

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

Примечание

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

Added in version 3.10.

Py_TPFLAGS_MAPPING

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

Примечание

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

** Наследство:**

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

См.также

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

Added in version 3.10.

Py_TPFLAGS_SEQUENCE

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

Примечание

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

** Наследство:**

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

См.также

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

Added in version 3.10.

Py_TPFLAGS_VALID_VERSION_TAG

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

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

Этот флаг присутствует в заголовочных файлах, но является внутренней функцией и не должен использоваться. Он будет удален в будущей версии CPython

const char *PyTypeObject.tp_doc

Необязательный указатель на NUL-терминированную C-строку, содержащую документальную строку для данного объекта типа. Он отображается как атрибут __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 и поэтому не может быть частью цикла ссылок.

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

Типы кучи (Py_TPFLAGS_HEAPTYPE) должны указывать на свой тип с помощью:

Py_VISIT(Py_TYPE(self));

Она необходима только начиная с версии Python 3.9. Для поддержки Python 3.8 и старше эта строка должна быть условной:

#if PY_VERSION_HEX >= 0x03090000
    Py_VISIT(Py_TYPE(self));
#endif

Если в поле tp_flags установлен бит Py_TPFLAGS_MANAGED_DICT, функция обхода должна вызвать PyObject_VisitManagedDict() следующим образом:

PyObject_VisitManagedDict((PyObject*)self, visit, arg);

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

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

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

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

Изменено в версии 3.9: Предполагается, что типы, выделенные из кучи, будут посещать Py_TYPE(self) в tp_traverse. В более ранних версиях Python, из-за bug 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 (из-за финализаторов или обратных вызовов weakref, связанных с содержащимся объектом). Если такой код может снова обратиться к self, важно, чтобы указатель на содержащийся объект был NULL в это время, чтобы self знал, что содержащийся объект больше не может быть использован. Макрос Py_CLEAR() выполняет операции в безопасном порядке.

Если в поле tp_flags установлен бит Py_TPFLAGS_MANAGED_DICT, функция обхода должна вызвать PyObject_ClearManagedDict() следующим образом:

PyObject_ClearManagedDict((PyObject*)self);

Обратите внимание, что 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 (например, это могут быть инты или плавающие числа C). Третий аргумент задает запрашиваемую операцию, как и для PyObject_RichCompare().

Возвращаемое значение - новый strong reference.

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

Added in version 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_weaklist.

** Наследство:**

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

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

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

getiterfunc PyTypeObject.tp_iter

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

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

PyObject *tp_iter(PyObject *self);

** Наследство:**

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

iternextfunc PyTypeObject.tp_iternext

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

PyObject *tp_iternext(PyObject *self);

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

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

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

** Наследство:**

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

struct PyMethodDef *PyTypeObject.tp_methods

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

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

** Наследство:**

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

struct PyMemberDef *PyTypeObject.tp_members

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

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

** Наследство:**

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

struct PyGetSetDef *PyTypeObject.tp_getset

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

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

** Наследство:**

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

PyTypeObject *PyTypeObject.tp_base

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

Примечание

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

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

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

** Наследство:**

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

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

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

PyObject *PyTypeObject.tp_dict

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

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

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

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

** Наследство:**

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

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

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

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

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

descrgetfunc PyTypeObject.tp_descr_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_WEAKREF, так и tp_dictoffset.

** Наследство:**

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

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

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

Если в поле tp_flags установлен бит 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 и устанавливает исключение при ошибке.

** Наследство:**

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

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

Для static types это поле не имеет значения по умолчанию.

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.

** Наследство:**

Это поле наследуется подтипами, за исключением того, что оно не наследуется static types, чей tp_base является NULL или &PyBaseObject_Type.

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

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

freefunc PyTypeObject.tp_free

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

void tp_free(void *self);

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

** Наследство:**

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

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

В динамических подтипах это поле устанавливается в деаллокатор, соответствующий 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 определяет эту функцию, чтобы отличить статически от dynamically allocated types).

** Наследство:**

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

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

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

PyObject *PyTypeObject.tp_bases

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

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

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

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

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

** Наследство:**

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

PyObject *PyTypeObject.tp_mro

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

Это поле должно иметь значение 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, даже если добавлены weakrefs. Вместо этого слабые ссылки для каждого типа хранятся в 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;

    /* Save the current exception, if any. */
    PyErr_Fetch(&error_type, &error_value, &error_traceback);

    /* ... */

    /* Restore the saved exception. */
    PyErr_Restore(error_type, error_value, error_traceback);
}

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

** Наследство:**

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

Added in version 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__().

** Наследство:**

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

Added in version 3.9: (поле существует с версии 3.8, но используется только с версии 3.9)

unsigned char PyTypeObject.tp_watched

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

Added in version 3.12.

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

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

Это приводит к появлению типов, которые ограничены относительно типов, определенных в Python:

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

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

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

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

Типы кучи

Альтернативой static types являются выделенные из кучи типы, или выделенные из кучи типы, которые близко соответствуют классам, созданным с помощью оператора class в Python. Для типов кучи установлен флаг Py_TPFLAGS_HEAPTYPE.

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

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

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

Сопоставление структур объектов

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, объект не поддерживает назначение и удаление элементов.

Структуры объектов последовательности

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_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.

Структуры буферных объектов

type PyBufferProcs

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

getbufferproc PyBufferProcs.bf_getbuffer

Эта функция имеет следующую сигнатуру:

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

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

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

  2. Заполните необходимые поля.

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

  4. Установите view->obj на экспортер и увеличьте view->obj.

  5. Возврат 0.

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

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

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

Отдельные поля view описаны в разделе Buffer structure, правила, как экспортер должен реагировать на конкретные запросы, - в разделе Buffer request types.

Вся память, на которую указывает структура 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, освободите всю память, связанную с view.

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

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

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

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

Added in version 3.5.

type PyAsyncMethods

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

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

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

Эта функция имеет следующую сигнатуру:

PyObject *am_await(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_aiter

Эта функция имеет следующую сигнатуру:

PyObject *am_aiter(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_anext

Эта функция имеет следующую сигнатуру:

PyObject *am_anext(PyObject *self);

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

sendfunc PyAsyncMethods.am_send

Эта функция имеет следующую сигнатуру:

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

Подробности см. в разделе PyIter_Send(). Для этого слота может быть установлено значение NULL.

Added in version 3.10.

Типефикаторы типов слотов

typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Часть Стабильный ABI.

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

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

typedef void (*destructor)(PyObject*)
Часть Стабильный ABI.
typedef void (*freefunc)(void*)

См. tp_free.

typedef PyObject *(*newfunc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.

См. tp_new.

typedef int (*initproc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.

См. tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Часть Стабильный ABI.

См. tp_repr.

typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)
Часть Стабильный ABI.

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

typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)
Часть Стабильный ABI.

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

typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)
Часть Стабильный ABI.

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

См. tp_getattro.

typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)
Часть Стабильный ABI.

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

См. tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.

См. tp_descr_get.

typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.

См. tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Часть Стабильный ABI.

См. tp_hash.

typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)
Часть Стабильный ABI.

См. tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Часть Стабильный ABI.

См. tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Часть Стабильный ABI.

См. tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Часть Стабильный ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
Часть Стабильный ABI с версии 3.12.
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
Часть Стабильный ABI с версии 3.12.
typedef PyObject *(*unaryfunc)(PyObject*)
Часть Стабильный ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Часть Стабильный ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

См. am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Часть Стабильный ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)
Часть Стабильный ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Часть Стабильный ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Часть Стабильный ABI.

Примеры

Ниже приведены простые примеры определений типов в Python. Они включают в себя обычное использование, с которым вы можете столкнуться. Некоторые демонстрируют сложные угловые случаи. Дополнительные примеры, практическая информация и учебник приведены в Определение типов расширений: Учебник и Определение типов расширений: Разные темы.

Базовый static type:

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 */
};

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

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, который не может быть подклассифицирован и не может быть вызван для создания экземпляров (например, использует отдельную функцию factory func) с использованием флага 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,  // set to &PyUnicode_Type in module init
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

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

typedef struct {
    PyObject_HEAD
} MyObject;

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

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

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 *),
};