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

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

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

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

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

«tp slots»

PyTypeObject Слот 1

Type

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

Информация 2

O

T

D

I

<R> tp_name.

const char *

__name__

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

destructor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

__getattribute__, __getattr__

G

(tp_setattr)

setattrfunc

__setattr__, __delattr__

G

tp_as_async

PyAsyncMethods *

подслоты

%

tp_repr

reprfunc

__repr__

X

X

X

tp_as_number

PyNumberMethods *

подслоты

%

tp_as_sequence

PySequenceMethods *

подслоты

%

tp_as_mapping

PyMappingMethods *

подслоты

%

tp_hash

hashfunc

__hash__

X

G

tp_call

ternaryfunc

__call__

X

X

tp_str

reprfunc

__str__

X

X

tp_getattro

getattrofunc

__getattribute__, __getattr__

X

X

G

tp_setattro

setattrofunc

__setattr__, __delattr__

X

X

G

tp_as_buffer

PyBufferProcs *

%

tp_flags

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

X

X

?

tp_doc

const char *

__doc__

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

__lt__, __le__, __eq__, __ne__, __gt__, __ge__

X

G

tp_weaklistoffset

Py_ssize_t

X

?

tp_iter

getiterfunc

__iter__

X

tp_iternext

iternextfunc

__next__

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

__база__

X

tp_dict

PyObject *

__диктат__

?

tp_descr_get

descrgetfunc

__get__

X

tp_descr_set

descrsetfunc

__set__, __delete__

X

tp_dictoffset

Py_ssize_t

X

?

tp_init

initproc

__init__

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

__new__

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases

PyObject *

__базы__

~

<tp_mro

PyObject *

__mro__

~

[tp_cache]

PyObject *

[tp_subclasses]

PyObject *

__подклассы__.

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

__del__

X

tp_vectorcall

vectorcallfunc

1

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

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

подслоты

Слот

Type

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

am_await

unaryfunc

__ожидать__.

am_aiter

unaryfunc

__aiter__

am_anext

unaryfunc

__anext__

am_send

sendfunc

nb_add

binaryfunc

__add__ __radd__

nb_inplace_add

binaryfunc

__iadd__

nb_subtract

binaryfunc

__sub__ __rsub__

nb_inplace_subtract

binaryfunc

__isub__

nb_multiply

binaryfunc

__мул__ __рмул__

nb_inplace_multiply

binaryfunc

__imul__

nb_remainder

binaryfunc

__mod__ __rmod__

nb_inplace_remainder

binaryfunc

__imod__

nb_divmod

binaryfunc

__divmod__ __rdivmod__

nb_power

ternaryfunc

__pow__ __rpow__

nb_inplace_power

ternaryfunc

__ipow__

nb_negative

unaryfunc

__neg__

nb_positive

unaryfunc

__pos__

nb_absolute

unaryfunc

__abs__

nb_bool

inquiry

__bool__

nb_invert

unaryfunc

__инвертировать__.

nb_lshift

binaryfunc

__lshift__ __rlshift__

nb_inplace_lshift

binaryfunc

__ilshift__

nb_rshift

binaryfunc

__rrshift__ __rrshift__

nb_inplace_rshift

binaryfunc

__irshift__

nb_and

binaryfunc

__and__ __rand__

nb_inplace_and

binaryfunc

__iand__

nb_xor

binaryfunc

__xor__ __rxor__

nb_inplace_xor

binaryfunc

__ixor__.

nb_or

binaryfunc

__ор__ __рор__

nb_inplace_or

binaryfunc

__ior__

nb_int

unaryfunc

__int__

nb_reserved

void *

nb_float

unaryfunc

__float__

nb_floor_divide

binaryfunc

__floordiv__

nb_inplace_floor_divide

binaryfunc

__ifloordiv__

nb_true_divide

binaryfunc

__truediv__

nb_inplace_true_divide

binaryfunc

__itruediv__

nb_index

unaryfunc

__index__

nb_matrix_multiply

binaryfunc

__matmul__ __rmatmul__

nb_inplace_matrix_multiply

binaryfunc

__imatmul__

mp_length

lenfunc

__len__

mp_subscript

binaryfunc

__getitem__

mp_ass_subscript

objobjargproc

__setitem__, __delitem__

sq_length

lenfunc

__len__

sq_concat

binaryfunc

__add__

sq_repeat

ssizeargfunc

__mul__

sq_item

ssizeargfunc

__getitem__

sq_ass_item

ssizeobjargproc

__setitem__ __delitem__

sq_contains

objobjproc

__содержит__.

sq_inplace_concat

binaryfunc

__iadd__

sq_inplace_repeat

ssizeargfunc

__imul__

bf_getbuffer

getbufferproc()

bf_releasebuffer

releasebufferproc()

типы слотов

typedef

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

Тип возврата

allocfunc

PyObject *

destructor

void *

void

freefunc

void *

void

traverseproc

void *
void *

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

const char *

PyObject *

setattrfunc

const char *

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

int

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

int

releasebufferproc

void

inquiry

void *

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;
} PyTypeObject;

Слоты PyObject

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

Py_ssize_t PyObject.ob_refcnt
Part of the Stable ABI.

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

Наследственность:

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

PyTypeObject *PyObject.ob_type
Part of the Stable ABI.

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

Foo_Type.ob_type = &PyType_Type;

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

Наследственность:

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

PyObject *PyObject._ob_next
PyObject *PyObject._ob_prev

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

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

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

Наследственность:

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

Слоты PyVarObject

Py_ssize_t PyVarObject.ob_size
Part of the Stable ABI.

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

Наследственность:

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

Слоты PyTypeObject

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

const char *PyTypeObject.tp_name

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

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

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

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

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

Наследственность:

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

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

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

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

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

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

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

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

Наследственность:

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

destructor PyTypeObject.tp_dealloc

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

void tp_dealloc(PyObject *self);

Функция деструктора вызывается макросами Py_DECREF() и Py_XDECREF(), когда количество новых ссылок равно нулю. В этот момент экземпляр все еще существует, но ссылок на него нет. Функция деструктора должна освободить все ссылки, принадлежащие экземпляру, освободить все буферы памяти, принадлежащие экземпляру (используя функцию освобождения, соответствующую функции выделения, использованной для выделения буфера), и вызвать функцию типа tp_free. Если тип не является подтипируемым (не имеет установленного бита флага Py_TPFLAGS_BASETYPE), допустимо вызывать деаллокатор объектов напрямую, а не через tp_free. Деаллокатор объекта должен быть тем, который использовался для выделения экземпляра; обычно это PyObject_Del(), если экземпляр был выделен с помощью PyObject_New() или PyObject_VarNew(), или 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), то после вызова деаллокатора типа деаллокатор должен уменьшить счетчик ссылок для своего объекта типа. Чтобы избежать висячих указателей, рекомендуется следующий способ:

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

Наследственность:

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

Py_ssize_t PyTypeObject.tp_vectorcall_offset

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

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

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

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

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

Не рекомендуется, чтобы heap types реализовывал протокол vectorcall. Когда пользователь устанавливает __call__ в коде Python, обновляется только tp_call, что, вероятно, делает его несовместимым с функцией vectorcall.

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

Наследственность:

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

getattrfunc PyTypeObject.tp_getattr

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

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

Наследственность:

Группа: tp_getattr, tp_getattro

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

setattrfunc PyTypeObject.tp_setattr

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

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

Наследственность:

Группа: tp_setattr, tp_setattro

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

PyAsyncMethods *PyTypeObject.tp_as_async

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

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

Наследственность:

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

reprfunc PyTypeObject.tp_repr

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

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

PyObject *tp_repr(PyObject *self);

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

Наследственность:

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

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

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

PyNumberMethods *PyTypeObject.tp_as_number

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

Наследственность:

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

PySequenceMethods *PyTypeObject.tp_as_sequence

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

Наследственность:

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

PyMappingMethods *PyTypeObject.tp_as_mapping

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

Наследственность:

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

hashfunc PyTypeObject.tp_hash

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

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

Py_hash_t tp_hash(PyObject *);

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

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

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

Наследственность:

Группа: tp_hash, tp_richcompare

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

ternaryfunc PyTypeObject.tp_call

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

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

Наследственность:

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

reprfunc PyTypeObject.tp_str

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

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

PyObject *tp_str(PyObject *self);

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

Наследственность:

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

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

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

getattrofunc PyTypeObject.tp_getattro

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

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

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

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

Наследственность:

Группа: tp_getattr, tp_getattro

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

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

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

setattrofunc PyTypeObject.tp_setattro

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

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

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

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

Наследственность:

Группа: tp_setattr, tp_setattro

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

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

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

PyBufferProcs *PyTypeObject.tp_as_buffer

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

Наследственность:

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

unsigned long PyTypeObject.tp_flags

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

Наследственность:

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

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

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

Бит-маски:

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

Py_TPFLAGS_HEAPTYPE

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

Наследственность:

???

Py_TPFLAGS_BASETYPE

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

Наследственность:

???

Py_TPFLAGS_READY

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

Наследственность:

???

Py_TPFLAGS_READYING

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

Наследственность:

???

Py_TPFLAGS_HAVE_GC

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

Наследственность:

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

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

Py_TPFLAGS_DEFAULT

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

Наследственность:

???

Py_TPFLAGS_METHOD_DESCRIPTOR

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

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

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

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

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

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

Наследственность:

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

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 protocol. Подробности смотрите в tp_vectorcall_offset.

Наследственность:

Этот бит наследуется для static subtypes, если также наследуется tp_call. Heap types не наследуется Py_TPFLAGS_HAVE_VECTORCALL.

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

Py_TPFLAGS_IMMUTABLETYPE

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

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

Наследственность:

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

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

Py_TPFLAGS_DISALLOW_INSTANTIATION

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

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

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

Наследственность:

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

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

const char *PyTypeObject.tp_doc

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

Наследственность:

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

traverseproc PyTypeObject.tp_traverse

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

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

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

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

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

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

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

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

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

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

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

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

Наследственность:

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

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

inquiry PyTypeObject.tp_clear

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

int tp_clear(PyObject *);

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

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

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

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

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

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

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

Наследственность:

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

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

richcmpfunc PyTypeObject.tp_richcompare

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

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

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

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

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

Постоянная

Сравнение

Py_LT

<

Py_LE

<=

Py_EQ

==

Py_NE

!=

Py_GT

>

Py_GE

>=

Следующий макрос определен для облегчения написания богатых функций сравнения:

Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

Возвращает Py_True или Py_False из функции, в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочены операторами сравнения языка Си (например, это могут быть инты или плавающие числа). Третий аргумент задает запрашиваемую операцию, как для 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

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

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

Наследственность:

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

Когда тип, определенный оператором class, не имеет объявления __slots__, и ни один из его базовых типов не является слабоссылаемым, тип делается слабоссылаемым путем добавления в схему экземпляра головного слота списка слабых ссылок и установки tp_weaklistoffset смещения этого слота.

Когда объявление типа __slots__ содержит слот с именем __weakref__, этот слот становится главой списка слабых ссылок для экземпляров типа, а смещение слота хранится в tp_weaklistoffset типа.

Если объявление типа __slots__ не содержит слота с именем __weakref__, тип наследует свой tp_weaklistoffset от своего базового типа.

getiterfunc PyTypeObject.tp_iter

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

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

PyObject *tp_iter(PyObject *self);

Наследственность:

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

iternextfunc PyTypeObject.tp_iternext

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

PyObject *tp_iternext(PyObject *self);

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

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

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

Наследственность:

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

struct PyMethodDef *PyTypeObject.tp_methods

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

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

Наследственность:

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

struct PyMemberDef *PyTypeObject.tp_members

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

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

Наследственность:

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

struct PyGetSetDef *PyTypeObject.tp_getset

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

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

Наследственность:

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

PyTypeObject *PyTypeObject.tp_base

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

Примечание

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

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

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

Наследственность:

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

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

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

PyObject *PyTypeObject.tp_dict

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

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

Наследственность:

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

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

Если это поле 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

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

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

Если значение этого поля больше нуля, оно определяет смещение от начала структуры экземпляра. Если значение меньше нуля, оно определяет смещение от конца структуры экземпляра. Отрицательное смещение требует больших затрат и должно использоваться только в том случае, если структура экземпляра содержит часть переменной длины. Это используется, например, для добавления словаря переменных экземпляра к подтипам str или tuple. Обратите внимание, что поле tp_basicsize должно учитывать словарь, добавленный в конец в этом случае, даже если словарь не включен в основную структуру объекта. В системе с размером указателя 4 байта, tp_dictoffset должно быть установлено в -4, чтобы указать, что словарь находится в самом конце структуры.

Смещение реального словаря в экземпляре может быть вычислено из отрицательного tp_dictoffset следующим образом:

dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset
if dictoffset is not aligned on sizeof(void*):
    round up to sizeof(void*)

где tp_basicsize, tp_itemsize и tp_dictoffset берутся из объекта типа, а ob_size - из экземпляра. Абсолютное значение берется потому, что ints использует знак ob_size для хранения знака числа. (Никогда не нужно выполнять это вычисление самостоятельно; за вас это делает _PyObject_GetDictPtr()).

Наследственность:

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

Когда тип, определенный оператором class, не имеет объявления __slots__, и ни один из его базовых типов не имеет словаря переменных экземпляра, в схему экземпляра добавляется слот словаря, а параметр tp_dictoffset устанавливается на смещение этого слота.

Когда тип, определенный оператором class, имеет объявление __slots__, тип наследует свои tp_dictoffset от своего базового типа.

(Добавление слота с именем __dict__ к объявлению __slots__ не дает ожидаемого эффекта, а только вызывает путаницу. Возможно, это следует добавить в качестве функции, как и __weakref__).

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

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

initproc PyTypeObject.tp_init

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

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

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

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

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

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

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

Наследственность:

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

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

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

allocfunc PyTypeObject.tp_alloc

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

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

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

Наследственность:

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

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

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

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

newfunc PyTypeObject.tp_new

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

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

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

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

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

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

Наследственность:

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

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

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

freefunc PyTypeObject.tp_free

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

void tp_free(void *self);

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

Наследственность:

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

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

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

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

inquiry PyTypeObject.tp_is_gc

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

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

int tp_is_gc(PyObject *self);

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

Наследственность:

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

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

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

PyObject *PyTypeObject.tp_bases

Множество базовых типов.

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

Наследственность:

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

PyObject *PyTypeObject.tp_mro

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

Наследственность:

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

PyObject *PyTypeObject.tp_cache

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

Наследственность:

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

PyObject *PyTypeObject.tp_subclasses

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

Наследственность:

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

PyObject *PyTypeObject.tp_weaklist

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

Наследственность:

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

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

Чтобы это поле учитывалось (даже при наследовании), необходимо также установить бит флага Py_TPFLAGS_HAVE_FINALIZE.

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

Наследственность:

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

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

См.также

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

vectorcallfunc PyTypeObject.tp_vectorcall

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

Наследственность:

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

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

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

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

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

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

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

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

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

Типы куч

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

Это делается путем заполнения структуры PyType_Spec и вызова PyType_FromSpec(), PyType_FromSpecWithBases() или PyType_FromModuleAndSpec().

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

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(), PyObject_SetSlice() и PyObject_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

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

getbufferproc PyBufferProcs.bf_getbuffer

Сигнатура этой функции следующая:

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

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

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

  2. Заполните требуемые поля.

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

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

  5. Возврат 0.

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

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

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

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

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

PyBuffer_FillInfo() обеспечивает простой способ раскрытия простого байтового буфера и при этом корректно работает со всеми типами запросов.

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

releasebufferproc PyBufferProcs.bf_releasebuffer

Сигнатура этой функции следующая:

void (PyObject *exporter, Py_buffer *view);

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

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

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

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

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

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

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

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

type PyAsyncMethods

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

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

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

Сигнатура этой функции следующая:

PyObject *am_await(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_aiter

Сигнатура этой функции следующая:

PyObject *am_aiter(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_anext

Сигнатура этой функции следующая:

PyObject *am_anext(PyObject *self);

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

sendfunc PyAsyncMethods.am_send

Сигнатура этой функции следующая:

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

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

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

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

typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)
Part of the Stable ABI.

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

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

typedef void (*destructor)(PyObject*)
Part of the Stable ABI.
typedef void (*freefunc)(void*)

См. tp_free.

typedef PyObject *(*newfunc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.

См. tp_new.

typedef int (*initproc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.

См. tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Part of the Stable ABI.

См. tp_repr.

typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)
Part of the Stable ABI.

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

typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)
Part of the Stable ABI.

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

typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)
Part of the Stable ABI.

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

См. tp_getattro.

typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)
Part of the Stable ABI.

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

См. tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.

См. tp_descr_get.

typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.

См. tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Part of the Stable ABI.

См. tp_hash.

typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)
Part of the Stable ABI.

См. tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Part of the Stable ABI.

См. tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Part of the Stable ABI.

См. tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Part of the Stable ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
typedef PyObject *(*unaryfunc)(PyObject*)
Part of the Stable ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Part of the Stable ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

См. am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Part of the Stable ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t)
Part of the Stable ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Part of the Stable ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Part of the Stable ABI.

Примеры

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

Базовый static type:

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

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

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

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

Тип, поддерживающий weakrefs, instance dicts и hashing:

typedef struct {
    PyObject_HEAD
    const char *data;
    PyObject *inst_dict;
    PyObject *weakreflist;
} 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_weaklistoffset = offsetof(MyObject, weakreflist),
    .tp_dictoffset = offsetof(MyObject, inst_dict),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
    .tp_new = myobj_new,
    .tp_traverse = (traverseproc)myobj_traverse,
    .tp_clear = (inquiry)myobj_clear,
    .tp_alloc = PyType_GenericNew,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
    .tp_hash = (hashfunc)myobj_hash,
    .tp_richcompare = PyBaseObject_Type.tp_richcompare,
};

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

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

static PyTypeObject MyStr_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyStr",
    .tp_basicsize = sizeof(MyStr),
    .tp_base = NULL,  // set to &PyUnicode_Type in module init
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

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

typedef struct {
    PyObject_HEAD
} MyObject;

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

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

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

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject) - sizeof(char *),
    .tp_itemsize = sizeof(char *),
};
Вернуться на верх