Введите объекты

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

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

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

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

«слоты tp»

Слот PyTypeObject

Type

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

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

O

T

D

Я

<R> tp_name

постоянный символ *

__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

__получить атрибут__, __getattr__

G

(tp_setattr)

setattrfunc

__установить значение__, __удалить значение__

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

__стр__

X

X

tp_getattro

getattrofunc

__получить атрибут__, __getattr__

X

X

G

tp_setattro

setattrofunc

__установить значение__, __удалить значение__

X

X

G

tp_as_buffer

PyBufferProcs *

%

tp_flags

неподписанный длинный

X

X

?

tp_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

__итер__

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 *

__дикт__

?

tp_descr_get

descrgetfunc

__get__

X

tp_descr_set

descrsetfunc

__установить__, __удалить__

X

tp_dictoffset

Py_ssize_t

X

?

tp_init

initproc

__инит__

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 *

__мро__

~

[tp_cache]

PyObject *

[tp_subclasses]

PyObject *

__подклассы__

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

неподписанный int

tp_finalize

destructor

__дел__

X

tp_vectorcall

vectorcallfunc

дополнительные слоты

Слот

Type

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

am_await

unaryfunc

__await__

am_aiter

unaryfunc

__aiter__

am_anext

unaryfunc

__анекст__

am_send

sendfunc

nb_add

binaryfunc

__добавить__ __радд__

nb_inplace_add

binaryfunc

__иадд__

nb_subtract

binaryfunc

__sub__ __рсуб__

nb_inplace_subtract

binaryfunc

__изуб__

nb_multiply

binaryfunc

__мул__ __рмул__

nb_inplace_multiply

binaryfunc

__имуль__

nb_remainder

binaryfunc

__мод__ __rmod__

nb_inplace_remainder

binaryfunc

__имод__

nb_divmod

binaryfunc

__divmod__ __rdivmod____

nb_power

ternaryfunc

__бах__ __rpow__

nb_inplace_power

ternaryfunc

__пов__

nb_negative

unaryfunc

__нег__

nb_positive

unaryfunc

__пос__

nb_absolute

unaryfunc

__abs (в )__

nb_bool

inquiry

__бул__

nb_invert

unaryfunc

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

nb_lshift

binaryfunc

__lshift__ __rlshift сдвиг__

nb_inplace_lshift

binaryfunc

__илшифт__

nb_rshift

binaryfunc

__ршифт__ __рршифт__

nb_inplace_rshift

binaryfunc

__irshift__

nb_and

binaryfunc

__и__ __рэнд__

nb_inplace_and

binaryfunc

__ианд__

nb_xor

binaryfunc

__xor__ __rxor__

nb_inplace_xor

binaryfunc

__иксор__

nb_or

binaryfunc

__или__ __ror__

nb_inplace_or

binaryfunc

__иор__

nb_int

unaryfunc

__инт__

nb_reserved

пустота *

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

__итруэдив__

nb_index

unaryfunc

__индекс__

nb_matrix_multiply

binaryfunc

__матмул__ __рматмул__

nb_inplace_matrix_multiply

binaryfunc

__иматмуль__

mp_length

lenfunc

__лен__

mp_subscript

binaryfunc

__getitem ( начало )__

mp_ass_subscript

objobjargproc

__установить__, __удалить__

sq_length

lenfunc

__лен__

sq_concat

binaryfunc

__add__

sq_repeat

ssizeargfunc

__муль__

sq_item

ssizeargfunc

__getitem ( начало )__

sq_ass_item

ssizeobjargproc

__установить__ __делитем__

sq_contains

objobjproc

__contains__

sq_inplace_concat

binaryfunc

__иадд__

sq_inplace_repeat

ssizeargfunc

__имуль__

bf_getbuffer

getbufferproc()

bf_releasebuffer

releasebufferproc()

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

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

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

Возвращаемый тип

allocfunc

PyObject *

destructor

PyObject *

пустота

freefunc

пустота *

пустота

traverseproc

пустота *

инт

newfunc

PyObject *

initproc

инт

reprfunc

PyObject *

PyObject *

getattrfunc

постоянный символ *

PyObject *

setattrfunc

постоянный символ *

инт

getattrofunc

PyObject *

setattrofunc

инт

descrgetfunc

PyObject *

descrsetfunc

инт

hashfunc

PyObject *

Py_hash_t

richcmpfunc

инт

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

инт

инт

releasebufferproc

пустота

inquiry

PyObject *

инт

unaryfunc

PyObject *

binaryfunc

PyObject *

ternaryfunc

PyObject *

ssizeargfunc

PyObject *

ssizeobjargproc

инт

objobjproc

инт

objobjargproc

инт

Смотрите Тип слота typedefs ниже для получения более подробной информации.

Определение 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

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

Py_ssize_t PyObject.ob_refcnt
Part of the Стабильный ABI.

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

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

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

PyTypeObject *PyObject.ob_type
Part of the Стабильный 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 Стабильный ABI.

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

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

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

Слоты PyTypeObject

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

const char *PyTypeObject.tp_name

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

Для dynamically allocated type objects это должно быть просто имя типа, а имя модуля явно сохранено в type dict как значение для ключа '__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). Ответственность за то, чтобы: c:member:~PyTypeObject.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. Средство освобождения объекта должно использоваться для выделения экземпляра; обычно это: c:func:PyObject_Del, если экземпляр был выделен с использованием:c:macro:PyObject_New или PyObject_NewVar, или PyObject_GC_Del() если экземпляр был выделен с использованием PyObject_GC_New или PyObject_GC_NewVar.

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

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

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

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

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

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

Py_ssize_t PyTypeObject.tp_vectorcall_offset

Необязательное смещение для функции для каждого экземпляра, которая реализует вызов объекта с использованием vectorcall protocol, более эффективной альтернативы более простому: c:member:~PyTypeObject.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().

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

Не рекомендуется для mutable heap types реализовывать протокол вызова vector. Когда пользователь устанавливает __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(). Это, в частности, относится к типам без установленного флага Py_TPFLAGS_IMMUTABLETYPE (включая подклассы, определенные в Python).

getattrfunc PyTypeObject.tp_getattr

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

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

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

Группа: tp_getattr, tp_getattro

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

setattrfunc PyTypeObject.tp_setattr

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

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

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

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

Подпись такая же, как и для PyObject_GetAttr():

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

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

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

Группа: tp_getattr, tp_getattro

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

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

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

setattrofunc PyTypeObject.tp_setattro

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

Подпись такая же, как и для PyObject_SetAttr():

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

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

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

Группа: tp_setattr, tp_setattro

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

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

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

PyBufferProcs *PyTypeObject.tp_as_buffer

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

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

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

unsigned long PyTypeObject.tp_flags

Это поле представляет собой битовую маску из различных флагов. Некоторые флаги указывают на вариантную семантику для определенных ситуаций; другие используются для указания того, что определенные поля в type object (или в структурах расширения, на которые ссылаются через 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 его экземпляров считается ссылкой на тип, а объект type увеличивается при создании нового экземпляра и уменьшается при уничтожении экземпляра (это не относится к экземплярам подтипов; только к объекту type). тип, на который ссылается ob_type экземпляра, увеличивается или УМЕНЬШАЕТСЯ).

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

???

Py_TPFLAGS_BASETYPE

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

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

???

Py_TPFLAGS_READY

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

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

???

Py_TPFLAGS_READYING

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

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

???

Py_TPFLAGS_HAVE_GC

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

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

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

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

Py_TPFLAGS_DEFAULT

Это битовая маска всех битов, которые относятся к существованию определенных полей в type object и его структурах расширения. В настоящее время она включает следующие биты: 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_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.

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

Этот бит наследуется для типов с установленным флагом Py_TPFLAGS_IMMUTABLETYPE, если также наследуется tp_call.

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

Py_TPFLAGS_IMMUTABLETYPE

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

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

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

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

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

Py_TPFLAGS_DISALLOW_INSTANTIATION

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

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

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

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

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

Примечание

Чтобы запретить прямое создание экземпляра класса, но разрешить создание экземпляра его подклассов (например, для abstract base class), не используйте этот флаг. Вместо этого сделайте:c:member:~PyTypeObject.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.

const char *PyTypeObject.tp_doc

Необязательный указатель на строку 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() для каждого из членов instances, которые являются объектами 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), не должен ** посещаться, поскольку экземпляр напрямую не владеет слабыми ссылками на себя (список слабых ссылок существует ли поддержка механизма слабых ссылок, но экземпляр не имеет сильной ссылки на элементы внутри него, поскольку их разрешено удалять, даже если экземпляр все еще жив).

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

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

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

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

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

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

inquiry PyTypeObject.tp_clear

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

int tp_clear(PyObject *);

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

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

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

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

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

Возвращаемое значение является новым strong reference.

При ошибке устанавливает исключение и возвращает 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, если он присутствует); это смещение используется: c:func:PyObject_ClearWeakRefs и PyWeakref_* функции. Структура экземпляра должна включать поле типа PyObject*, которое инициализируется значением NULL.

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

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

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

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

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

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

getiterfunc PyTypeObject.tp_iter

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

Эта функция имеет ту же сигнатуру, что и:c:func: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.

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

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

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

Это поле по умолчанию имеет значение &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; это словарь атрибутов самого типа object.

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

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

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

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

Когда тип, определенный оператором class, не имеет объявления __slots__ и ни один из его базовых типов не имеет переменной экземпляра dictionary, в макет экземпляра добавляется ячейка словаря, а 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

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

Для этого поля должно быть установлено значение 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

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

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

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

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

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

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

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

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

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

См.также

«Завершение строительства безопасного объекта» (PEP 442)

vectorcallfunc PyTypeObject.tp_vectorcall

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

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

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

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

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

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

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

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

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

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

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

Типы кучи

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

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

Числовые структуры объектов

type PyNumberMethods

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

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

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

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

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 будет новой ссылкой на корневой объект.

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

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

Эта функция НЕ ДОЛЖНА уменьшать значение 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, т.е. c:func: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.

Тип слота typedefs

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

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

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

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

Смотрите tp_free.

typedef PyObject *(*newfunc)(PyObject*, PyObject*, PyObject*)
Part of the Стабильный ABI.

Смотрите tp_new.

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

Смотрите tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Part of the Стабильный ABI.

Смотрите tp_repr.

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

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

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

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

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

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

Смотрите tp_getattro.

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

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

Смотрите tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Part of the Стабильный ABI.

Смотрите tp_descr_get.

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

Смотрите tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Part of the Стабильный ABI.

Смотрите tp_hash.

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

Смотрите tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Part of the Стабильный ABI.

Смотрите tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Part of the Стабильный ABI.

Смотрите tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Part of the Стабильный ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
typedef PyObject *(*unaryfunc)(PyObject*)
Part of the Стабильный ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Part of the Стабильный ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

Смотрите am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Part of the Стабильный ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Part of the Стабильный ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)
Part of the Стабильный ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Part of the Стабильный ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Part of the Стабильный 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 и хэширование:

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, который не может быть подклассифицирован и не может быть вызван для создания экземпляров (например, использует отдельную фабричную функцию) с использованием флага 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 *),
};
Вернуться на верх