Spec-Zone.ru › Python 3.13

Структуры объектов типов

Возможно, одна из важнейших структур системы объектов 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()

__buffer__

bf_releasebuffer

releasebufferproc()

__release_buffer__

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

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

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

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

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

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

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

Слоты PyVarObject

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

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

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

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

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

Слоты PyTypeObject

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

const char *PyTypeObject.tp_name

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

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

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

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

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

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

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

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

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

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

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

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

Примечание

Для доступа к полю ob_size следует использовать макросы Py_SIZE() и Py_SET_SIZE().

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

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

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

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

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

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

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

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

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

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

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

destructor PyTypeObject.tp_dealloc

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

void tp_dealloc(PyObject *self);

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

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

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

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

static void foo_dealloc(foo_object *self) {
    PyTypeObject *tp = Py_TYPE(self);
    // free references and buffers here
    tp->tp_free(self);
    Py_DECREF(tp);
}

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

В Python со сборщиком мусора функция tp_dealloc может быть вызвана из любого потока Python, а не только из потока, создавшего объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Для вызовов Python API это не проблема, поскольку поток, в котором вызывается 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.

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

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

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

Сигнатура совпадает с сигнатурой 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

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

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

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

Добавлено в версии 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 и поэтому не может входить в цикл ссылок.

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

Типы в куче (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 необходимо посещать только те члены, которыми экземпляр владеет (то есть имеет на них сильные ссылки). Например, если объект поддерживает слабые ссылки через слот 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_flags установлен бит Py_TPFLAGS_MANAGED_DICT, функция обхода должна вызывать PyObject_ClearManagedDict() следующим образом:

PyObject_ClearManagedDict((PyObject*)self);

Обратите внимание, что 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().

Обычно перед вызовом PyType_Ready этому полю следует присвоить NULL; также ему можно присвоить словарь с начальными атрибутами типа. После инициализации типа функцией 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_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 и устанавливает исключение.

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

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

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

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

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

Кортеж, содержащий расширенный набор базовых типов в порядке разрешения методов: начиная с самого типа и заканчивая 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)
{
    /* Save the current exception, if any. */
    PyObject *exc = PyErr_GetRaisedException();

    /* ... */

    /* Restore the saved exception. */
    PyErr_SetRaisedException(exc);
}

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

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

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

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

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

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

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

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

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

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

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

releasebufferproc PyBufferProcs.bf_releasebuffer

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

void (PyObject *exporter, Py_buffer *view);

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

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

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

Эта функция НЕ ДОЛЖНА уменьшать счётчик ссылок view->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 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–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/c-api/typeobj.html

Spec-Zone.ru

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