Spec-Zone.ru › Python 3.12

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

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

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

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

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

«слоты tp»

Слот PyTypeObject [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

[1]

(): Имя слота в круглых скобках указывает на то, что он (фактически) устарел.

<>: Имена в угловых скобках изначально следует задавать значением NULL и считать доступными только для чтения.

[]: Имена в квадратных скобках предназначены только для внутреннего использования.

<R> (в качестве префикса) означает, что поле является обязательным (не должно быть NULL).

[2]

Столбцы:

«O»: задается для PyBaseObject_Type

«T»: задается для PyType_Type

«D»: значение по умолчанию (если для слота задано значение NULL)

X - PyType_Ready sets this value if it is NULL
~ - PyType_Ready always sets this value (it should be NULL)
? - PyType_Ready may set this value depending on other slots

Also see the inheritance column ("I").

«I»: наследование

X - type slot is inherited via *PyType_Ready* if defined with a *NULL* value
% - the slots of the sub-struct are inherited individually
G - inherited, but only in combination with other slots; see the slot's description
? - it's complicated; see the slot's description

Обратите внимание, что некоторые слоты фактически наследуются через обычную цепочку поиска атрибутов.

подслоты

Слот

Тип

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

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()

определения типов слотов

определение типа

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

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

allocfunc

PyObject *

destructor

PyObject *

void

freefunc

void *

void

traverseproc

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

PyObject *

setattrfunc

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

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(), обычно вызываемого из инструкции класса). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, а это означает, что его экземпляры (то есть объекты типов) должны иметь поле ob_size.

Py_ssize_t PyObject.ob_refcnt
Часть Стабильного ABI.

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

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

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

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() не изменяет это поле, если оно не равно нулю.

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

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

PyObject *PyObject._ob_next
PyObject *PyObject._ob_prev

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

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

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

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

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

Слоты PyVarObject

Py_ssize_t PyVarObject.ob_size
Часть Стабильного ABI.

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

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

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

Слоты PyTypeObject

Для каждого слота есть раздел с описанием наследования. Если PyType_Ready() может задать значение, когда поле установлено в NULL, то также будет раздел «По умолчанию». (Обратите внимание, что многие поля, заданные для 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.

Экземпляры типа с переменной длиной должны иметь поле ob_size, а размер экземпляра равен tp_basicsize плюс N, умноженное на tp_itemsize, где N — «длина» объекта. Значение N обычно хранится в поле ob_size экземпляра. Есть исключения: например, для обозначения отрицательного числа объекты типа int используют отрицательное значение 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);
}

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

В 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(), чтобы запретить наследование метода хеширования от родительского типа. На уровне Python это интерпретируется как эквивалент __hash__ = None, в результате чего 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

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

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

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

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

???

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

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

Если установлен этот флаг, следует также установить 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

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

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()

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

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

const char *PyTypeObject.tp_doc

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

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

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

Поскольку цель функций tp_clear — разрывать циклы ссылок, нет необходимости очищать содержащиеся объекты, такие как строки или целые числа 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().

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

При ошибке устанавливает исключение и возвращает из функции 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, проблем возникнуть не должно.

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

Если в поле tp_flags установлен бит Py_TPFLAGS_MANAGED_WEAKREF, то 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 и объявляющий вычисляемые атрибуты экземпляров этого типа.

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

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

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

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

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

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

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().

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

Это поле наследуется статическими подклассами, но не динамическими подклассами (подклассами, созданными оператором 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 определяет эту функцию, чтобы различать статические и динамически выделенные типы.)

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

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

Значение по умолчанию:

У этого слота нет значения по умолчанию. Если это поле равно 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

Кортеж, содержащий расширенный набор базовых типов в порядке разрешения методов (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, даже если добавлены слабые ссылки. Вместо этого слабые ссылки каждого из них хранятся в 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);
}

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

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

Добавлено в версии 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.

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

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

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

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

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

Типы в куче

Альтернативой статическим типам являются типы, выделяемые в куче, или, кратко, типы в куче. Они очень похожи на классы, создаваемые оператором 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_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

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

getbufferproc PyBufferProcs.bf_getbuffer

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

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

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

  1. Проверить, можно ли удовлетворить запрос. Если это невозможно, вызвать исключение BufferError, присвоить view->obj значение NULL и вернуть -1.
  2. Заполнить запрошенные поля.
  3. Увеличить внутренний счётчик количества экспортов.
  4. Присвоить view->obj значение exporter и увеличить значение view->obj.
  5. Вернуть 0.

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

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

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

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

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

Добавлено в версии 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.

Типы typedef слотов

typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Часть стабильного 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*)
Часть стабильного ABI.
typedef void (*freefunc)(void*)

См. tp_free.

typedef PyObject *(*newfunc)(PyTypeObject*, 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. Они иллюстрируют распространённые случаи использования. Некоторые демонстрируют непростые крайние случаи. Другие примеры, практические сведения и руководство см. в разделах Определение типов расширения: руководство и Определение типов расширения: разные темы.

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

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

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

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

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/c-api/typeobj.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API