Документация Python неофициальный перевод
Содержание страницы

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

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

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

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

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

“tp slots”

PyTypeObject Slot 1

Тип

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

Информация 2

O

T

D

I

<R> tp_name

const char *

name

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

destructor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

getattribute__, __getattr

G

(tp_setattr)

setattrfunc

setattr__, __delattr

G

tp_as_async

PyAsyncMethods *

подслоты

%

tp_repr

reprfunc

repr

X

X

X

tp_as_number

PyNumberMethods *

подслоты

%

tp_as_sequence

PySequenceMethods *

подслоты

%

tp_as_mapping

PyMappingMethods *

подслоты

%

tp_hash

hashfunc

hash

X

G

tp_call

ternaryfunc

call

X

X

tp_str

reprfunc

str

X

X

tp_getattro

getattrofunc

getattribute__, __getattr

X

X

G

tp_setattro

setattrofunc

setattr__, __delattr

X

X

G

tp_as_buffer

PyBufferProcs *

%

tp_flags

unsigned long

X

X

?

tp_doc

const char *

doc

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

lt__, __le__, __eq__, __ne__, __gt__, __ge

X

G

tp_weaklistoffset

Py_ssize_t

X

?

tp_iter

getiterfunc

iter

X

tp_iternext

iternextfunc

next

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

base

X

tp_dict

PyObject *

dict

?

tp_descr_get

descrgetfunc

get

X

tp_descr_set

descrsetfunc

set__, __delete

X

tp_dictoffset

Py_ssize_t

X

?

tp_init

initproc

init

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

new

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases>

PyObject *

bases

~

<tp_mro>

PyObject *

mro

~

[tp_cache]

PyObject *

[tp_subclasses]

PyObject *

subclasses

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

del

X

tp_vectorcall

vectorcallfunc

1

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

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

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

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

2

Столбцы:

“O”: устанавливается на PyBaseObject_Type

“T”: устанавливается на PyType_Type

“D”: значение по умолчанию (если слот установлен в NULL)

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

Also see the inheritance column ("I").

“I”: наследование

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

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

подслотыsub-slots

Слот

Тип

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

am_await

unaryfunc

await

am_aiter

unaryfunc

aiter

am_anext

unaryfunc

anext

am_send

sendfunc

nb_add

binaryfunc

add__ __radd

nb_inplace_add

binaryfunc

iadd

nb_subtract

binaryfunc

sub__ __rsub

nb_inplace_subtract

binaryfunc

isub

nb_multiply

binaryfunc

mul__ __rmul

nb_inplace_multiply

binaryfunc

imul

nb_remainder

binaryfunc

mod__ __rmod

nb_inplace_remainder

binaryfunc

imod

nb_divmod

binaryfunc

divmod__ __rdivmod

nb_power

ternaryfunc

pow__ __rpow

nb_inplace_power

ternaryfunc

ipow

nb_negative

unaryfunc

neg

nb_positive

unaryfunc

pos

nb_absolute

unaryfunc

abs

nb_bool

inquiry

bool

nb_invert

unaryfunc

invert

nb_lshift

binaryfunc

lshift__ __rlshift

nb_inplace_lshift

binaryfunc

ilshift

nb_rshift

binaryfunc

rshift__ __rrshift

nb_inplace_rshift

binaryfunc

irshift

nb_and

binaryfunc

and__ __rand

nb_inplace_and

binaryfunc

iand

nb_xor

binaryfunc

xor__ __rxor

nb_inplace_xor

binaryfunc

ixor

nb_or

binaryfunc

or__ __ror

nb_inplace_or

binaryfunc

ior

nb_int

unaryfunc

int

nb_reserved

void *

nb_float

unaryfunc

float

nb_floor_divide

binaryfunc

floordiv

nb_inplace_floor_divide

binaryfunc

ifloordiv

nb_true_divide

binaryfunc

truediv

nb_inplace_true_divide

binaryfunc

itruediv

nb_index

unaryfunc

index

nb_matrix_multiply

binaryfunc

matmul__ __rmatmul

nb_inplace_matrix_multiply

binaryfunc

imatmul

mp_length

lenfunc

len

mp_subscript

binaryfunc

getitem

mp_ass_subscript

objobjargproc

setitem__, __delitem

sq_length

lenfunc

len

sq_concat

binaryfunc

add

sq_repeat

ssizeargfunc

mul

sq_item

ssizeargfunc

getitem

sq_ass_item

ssizeobjargproc

setitem__ __delitem

sq_contains

objobjproc

contains

sq_inplace_concat

binaryfunc

iadd

sq_inplace_repeat

ssizeargfunc

imul

bf_getbuffer

getbufferproc()

bf_releasebuffer

releasebufferproc()

Синонимы типов слотовslot typedefs

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

Подробнее см. определения типов слотов ниже.

Определение PyTypeObjectPyTypeObject Definition

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

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* Для вывода в формате "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* Для выделения памяти */

    /* Методы для реализации стандартных операций */

    destructor tp_dealloc;
    Py_ssize_t tp_vectorcall_offset;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    PyAsyncMethods *tp_as_async; /* ранее известный как tp_compare (Python 2)
                                    или tp_reserved (Python 3) */
    reprfunc tp_repr;

    /* Наборы методов для стандартных классов */

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

    /* Дополнительные стандартные операции (здесь для двоичной совместимости) */

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

    /* Функции для доступа к объекту как к буферу ввода/вывода */
    PyBufferProcs *tp_as_buffer;

    /* Флаги для определения наличия опциональных/расширенных возможностей */
    unsigned long tp_flags;

    const char *tp_doc; /* Строка документации */

    /* Назначенное значение в версии 2.0 */
    /* вызов функции для всех доступных объектов */
    traverseproc tp_traverse;

    /* удаление ссылок на содержащиеся объекты */
    inquiry tp_clear;

    /* Назначенное значение в версии 2.1 */
    /* расширенные сравнения */
    richcmpfunc tp_richcompare;

    /* включение слабых ссылок */
    Py_ssize_t tp_weaklistoffset;

    /* Итераторы */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Дескриптор атрибутов и механизмы подклассов */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    // Сильная ссылка на тип в куче, заимствованная ссылка на статический тип
    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; /* Низкоуровневая процедура освобождения памяти */
    inquiry tp_is_gc; /* Для PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* порядок разрешения методов */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

    /* Метка версии кэша атрибутов типа. Добавлено в версии 2.6. */
    unsigned int tp_version_tag;

    destructor tp_finalize;
    vectorcallfunc tp_vectorcall;
} PyTypeObject;

Слоты PyObjectPyObject Slots

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

Py_ssize_t PyObject.ob_refcnt
Часть Stable ABI.

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

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

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

PyTypeObject *PyObject.ob_type
Часть 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. Для статически размещённых объектов эти поля всегда остаются NULL. Для динамически размещённых объектов эти два поля используются для включения объекта в двусвязный список всех живых объектов в куче.

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

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

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

Слоты PyVarObjectPyVarObject Slots

Py_ssize_t PyVarObject.ob_size
Часть Stable ABI.

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

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

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

Слоты PyTypeObjectPyTypeObject Slots

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

const char *PyTypeObject.tp_name

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

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

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

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

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

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

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

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

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

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

Для типа с экземплярами переменной длины экземпляры должны иметь ob_size поле, а размер экземпляра равен tp_basicsize плюс N умножить на tp_itemsize, где N – «длина» объекта. Значение N обычно хранится в поле ob_size экземпляра. Есть исключения: например, int использует отрицательное ob_size для обозначения отрицательного числа, и N равно abs(ob_size). Кроме того, наличие поля ob_size в структуре экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура для типа списка имеет экземпляры фиксированной длины, но при этом у этих экземпляров есть значимое поле 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), деаллокатор должен освободить принадлежащую ему ссылку на объект-тип (через Py_DECREF()) после вызова деаллокатора типа. Чтобы избежать висячих указателей, рекомендуемый способ сделать это:

static void foo_dealloc(foo_object *self) {
    PyTypeObject *tp = Py_TYPE(self);
    // Освободить ссылки и буферы здесь.
    tp->tp_free(self);
    Py_DECREF(tp);
}

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

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

Py_ssize_t PyTypeObject.tp_vectorcall_offset

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

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

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

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

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

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

getattrfunc PyTypeObject.tp_getattr

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

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

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

Группа: tp_getattr, tp_getattro

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

setattrfunc PyTypeObject.tp_setattr

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

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

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

Группа: tp_setattr, tp_setattro

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

PyAsyncMethods *PyTypeObject.tp_as_async

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

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

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

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

reprfunc PyTypeObject.tp_repr

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

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

PyObject *tp_repr(PyObject *self);

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

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

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

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

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

PyNumberMethods *PyTypeObject.tp_as_number

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

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

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

PySequenceMethods *PyTypeObject.tp_as_sequence

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

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

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

PyMappingMethods *PyTypeObject.tp_as_mapping

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

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

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

hashfunc PyTypeObject.tp_hash

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

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

Py_hash_t tp_hash(PyObject *);

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

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

Это поле можно явно установить в PyObject_HashNotImplemented(), чтобы заблокировать наследование хеш-метода от родительского типа. Это интерпретируется как эквивалент __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

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

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

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

Поле 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

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

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

???

Py_TPFLAGS_READY

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

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

???

Py_TPFLAGS_READYING

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

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

???

Py_TPFLAGS_HAVE_GC

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

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

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

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

Py_TPFLAGS_DEFAULT

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

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

???

Py_TPFLAGS_METHOD_DESCRIPTOR

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

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

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

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

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

Новое в версии 3.8.

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

Этот флаг никогда не наследуется heap-типами. Для типов расширения он наследуется всякий раз, когда наследуется 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. Подробнее см. tp_vectorcall_offset.

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

Этот бит наследуется для статических подтипов, если tp_call также наследуется. Heap-типы не наследуют Py_TPFLAGS_HAVE_VECTORCALL.

Новое в версии 3.9.

Py_TPFLAGS_IMMUTABLETYPE

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

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

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

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

Новое в версии 3.10.

Py_TPFLAGS_DISALLOW_INSTANTIATION

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

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

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

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

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

Примечание

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

Новое в версии 3.10.

Py_TPFLAGS_MAPPING

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

Примечание

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

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

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

См. также

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

Новое в версии 3.10.

Py_TPFLAGS_SEQUENCE

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

Примечание

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

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

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

См. также

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

Новое в версии 3.10.

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

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

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

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

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

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

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

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

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

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

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

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

inquiry PyTypeObject.tp_clear

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

int tp_clear(PyObject *);

Функция-член tp_clear используется для разрыва циклических ссылок в циклическом мусоре, обнаруженном сборщиком мусора. В совокупности все функции tp_clear в системе должны совместно разрывать все циклические ссылки. Это тонкий момент, и при любых сомнениях следует предоставить функцию tp_clear. Например, тип 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 (из-за финализаторов или колбэков слабых ссылок, связанных с содержащимся объектом). Если такой код может снова сослаться на 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 должны быть упорядочиваемыми с помощью операторов сравнения языка C (например, это могут быть значения типа int или float). Третий аргумент задаёт требуемую операцию, как и для 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

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

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

PyObject *tp_iter(PyObject *self);

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

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

iternextfunc PyTypeObject.tp_iternext

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

PyObject *tp_iternext(PyObject *self);

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

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

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

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

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

struct PyMethodDef *PyTypeObject.tp_methods

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

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

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

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

struct PyMemberDef *PyTypeObject.tp_members

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

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

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

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

struct PyGetSetDef *PyTypeObject.tp_getset

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

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

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

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

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

Необязательный указатель на функцию «descriptor 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 берётся из экземпляра. Абсолютное значение берётся, потому что целые числа используют знак ob_size для хранения знака числа. (Никогда не требуется выполнять это вычисление самостоятельно; оно делается за вас функцией _PyObject_GetDictPtr().)

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

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

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

Если тип, определённый с помощью оператора class, содержит объявление __slots__, тот тип наследует значение tp_dictoffset от своего базового типа.

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

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

Этот слот не имеет значения по умолчанию. Для статических типов, если поле равно 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 и устанавливает исключение при ошибке.

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

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

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

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

allocfunc PyTypeObject.tp_alloc

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

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

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

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

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

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

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

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

newfunc PyTypeObject.tp_new

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

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

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

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

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

Флаг Py_TPFLAGS_DISALLOW_INSTANTIATION используется для запрета создания экземпляров типа в Python.

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

Это поле наследуется подтипами, за исключением статических типов, у которых tp_base равно NULL или &PyBaseObject_Type.

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

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

freefunc PyTypeObject.tp_free

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

void tp_free(void *self);

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

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

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

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

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

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

inquiry PyTypeObject.tp_is_gc

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

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

int tp_is_gc(PyObject *self);

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

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

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

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

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

PyObject *PyTypeObject.tp_bases

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

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

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

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

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

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

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

PyObject *PyTypeObject.tp_mro

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

Это поле должно быть установлено в 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;

    /* Сохранить текущее исключение, если оно есть. */
    PyErr_Fetch(&error_type, &error_value, &error_traceback);

    /* ... */

    /* Восстановить сохранённое исключение. */
    PyErr_Restore(error_type, error_value, error_traceback);
}

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

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

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

Новое в версии 3.4.

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

См. также

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

vectorcallfunc PyTypeObject.tp_vectorcall

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

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

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

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

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

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

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

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

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

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

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

Кучные типыHeap Types

Альтернативой статическим типам являются кучные типы (heap-allocated types), или кучные типы (heap types) для краткости. Они очень похожи на классы, создаваемые с помощью оператора class. У кучных типов установлен флаг Py_TPFLAGS_HEAPTYPE.

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

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

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

Структуры объектов отображенияMapping Object Structures

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

Структуры объектов последовательностейSequence Object Structures

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\nзаполнен, он вызывается, и длина последовательности используется для вычисления положительного\nиндекса, который передаётся в sq_item. Если sq_length равно NULL,\nиндекс передаётся функции как есть.

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.

Структуры объектов буфераBuffer Object Structures

type PyBufferProcs

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

getbufferproc PyBufferProcs.bf_getbuffer

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

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

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

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

  2. Заполнить запрошенные поля.

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

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

  5. Вернуть 0.

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

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

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

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

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

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

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

releasebufferproc PyBufferProcs.bf_releasebuffer

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

void (PyObject *exporter, Py_buffer *view);

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

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

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

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

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

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

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

Новое в версии 3.5.

type PyAsyncMethods

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

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

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

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

PyObject *am_await(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_aiter

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

PyObject *am_aiter(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_anext

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

PyObject *am_anext(PyObject *self);

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

sendfunc PyAsyncMethods.am_send

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

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

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

Новое в версии 3.10.

Определения типов слотовSlot Type typedefs

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

См. tp_free.

typedef PyObject *(*newfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_new.

typedef int (*initproc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_init.

typedef PyObject *(*reprfunc)(PyObject*)
Часть Stable ABI.

См. tp_repr.

typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)
Часть Stable ABI.

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

typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)
Часть Stable ABI.

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

typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)
Часть Stable ABI.

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

См. tp_getattro.

typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)
Часть Stable ABI.

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

См. tp_setattro.

typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_descr_get.

typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

См. tp_descr_set.

typedef Py_hash_t (*hashfunc)(PyObject*)
Часть Stable ABI.

См. tp_hash.

typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)
Часть Stable ABI.

См. tp_richcompare.

typedef PyObject *(*getiterfunc)(PyObject*)
Часть Stable ABI.

См. tp_iter.

typedef PyObject *(*iternextfunc)(PyObject*)
Часть Stable ABI.

См. tp_iternext.

typedef Py_ssize_t (*lenfunc)(PyObject*)
Часть Stable ABI.
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)
typedef PyObject *(*unaryfunc)(PyObject*)
Часть Stable ABI.
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)
Часть Stable ABI.
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

См. am_send.

typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)
Часть Stable ABI.
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)
Часть Stable ABI.
typedef int (*objobjproc)(PyObject*, PyObject*)
Часть Stable ABI.
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)
Часть Stable ABI.

ПримерыExamples

Ниже приведены простые примеры определений типов Python. Они включают распространённые варианты использования, с которыми можно столкнуться. Некоторые демонстрируют сложные граничные случаи. За дополнительными примерами, практической информацией и учебным пособием обращайтесь к Defining Extension Types: Tutorial и Defining Extension Types: Assorted Topics.

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

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

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

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

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

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

typedef struct {
    PyObject_HEAD
    const char *data;
    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,  // устанавливается в &PyUnicode_Type при инициализации модуля
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

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

typedef struct {
    PyObject_HEAD
} MyObject;

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

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

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

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject) - sizeof(char *),
    .tp_itemsize = sizeof(char *),
};