Spec-Zone.ru › Python 3.11

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

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

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

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

Быстрое справочное руководство

“tp slots”

Раздел объекта типа PyTypeObject 1

Тип

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

Информация 2

O

T

D

I

<R> tp_name

const char *

__name__

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

destructor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

__getattribute__, __getattr__

G

(tp_setattr)

setattrfunc

__setattr__, __delattr__

G

tp_as_async

PyAsyncMethods *

подразделы

%

tp_repr

reprfunc

__repr__

X

X

X

tp_as_number

PyNumberMethods *

подразделы

%

tp_as_sequence

PySequenceMethods *

подразделы

%

tp_as_mapping

PyMappingMethods *

подразделы

%

tp_hash

hashfunc

__hash__

X

G

tp_call

ternaryfunc

__call__

X

X

tp_str

reprfunc

__str__

X

X

tp_getattro

getattrofunc

__getattribute__, __getattr__

X

X

G

tp_setattro

setattrofunc

__setattr__, __delattr__

X

X

G

tp_as_buffer

PyBufferProcs *

%

tp_flags

unsigned long

X

X

?

tp_doc

const char *

__doc__

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

__lt__, __le__, __eq__, __ne__, __gt__, __ge__

X

G

tp_weaklistoffset

Py_ssize_t

X

?

tp_iter

getiterfunc

__iter__

X

tp_iternext

iternextfunc

__next__

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

__base__

X

tp_dict

PyObject *

__dict__

?

tp_descr_get

descrgetfunc

__get__

X

tp_descr_set

descrsetfunc

__set__, __delete__

X

tp_dictoffset

Py_ssize_t

X

?

tp_init

initproc

__init__

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

__new__

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases>

PyObject *

__bases__

~

<tp_mro>

PyObject *

__mro__

~

[tp_cache]

PyObject *

[tp_subclasses]

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

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

подслоты

Slot

Тип

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

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__

END_OF_DOCUMENT_MARKER

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

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

typedef

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

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

allocfunc

PyObject *

destructor

PyObject *

void

freefunc

void *

void

traverseproc

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

PyObject *

setattrfunc

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

int

releasebufferproc

void

inquiry

PyObject *

int

unaryfunc

PyObject *

binaryfunc

PyObject *

ternaryfunc

PyObject *

ssizeargfunc

PyObject *

ssizeobjargproc

int

objobjproc

int

objobjargproc

int

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

Определение PyTypeObject

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

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    Py_ssize_t tp_vectorcall_offset;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
                                    or tp_reserved (Python 3) */
    reprfunc tp_repr;

    /* Method suites for standard classes */

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

    /* More standard operations (here for binary compatibility) */

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

    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    unsigned long tp_flags;

    const char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    Py_ssize_t tp_weaklistoffset;

    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Attribute descriptor and subclassing stuff */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    // Strong reference on a heap type, borrowed reference on a static type
    struct _typeobject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    Py_ssize_t tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

    /* Type attribute cache version tag. Added in version 2.6 */
    unsigned int tp_version_tag;

    destructor tp_finalize;
    vectorcallfunc tp_vectorcall;
} PyTypeObject;

Слоты PyObject

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

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

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

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

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

PyTypeObject *PyObject.ob_type
Часть Стабильной ABI.

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

Foo_Type.ob_type = &PyType_Type;

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

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

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

PyObject *PyObject._ob_next
PyObject *PyObject._ob_prev

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

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

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

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

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

Слоты PyVarObject

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

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

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

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

Слоты PyTypeObject

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

const char *PyTypeObject.tp_name

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

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

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

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

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

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

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

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

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

unsigned long PyTypeObject.tp_flags

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

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

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

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

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

Битовые маски:

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

Py_TPFLAGS_HEAPTYPE

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

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

???

Py_TPFLAGS_BASETYPE

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

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

???

Py_TPFLAGS_READY

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

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

???

Py_TPFLAGS_READYING

Этот бит устанавливается во время процесса инициализации объекта типа функцией PyType_Ready().

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

???

Py_TPFLAGS_HAVE_GC

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

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

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

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

Py_TPFLAGS_DEFAULT

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

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

???

Py_TPFLAGS_METHOD_DESCRIPTOR

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

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

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

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

Введено в версии 3.8.

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

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

Py_TPFLAGS_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.

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

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

Введено в версии 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 (что возможно только через API на C).

Примечание

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

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

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

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

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

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

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

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

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

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

inquiry PyTypeObject.tp_clear

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

int tp_clear(PyObject *);

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

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

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

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

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

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

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

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

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

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

richcmpfunc PyTypeObject.tp_richcompare

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

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

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

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

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

Константа

Сравнение

Py_LT

<

Py_LE

<=

Py_EQ

==

Py_NE

!=

Py_GT

>

Py_GE

>=

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

Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

Возвращает Py_True или Py_False из функции, в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочиваемы операторами C сравнения (например, это могут быть целые числа или числа с плавающей точкой C). Третий аргумент указывает на запрашиваемую операцию, как и в PyObject_RichCompare().

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

В случае ошибки устанавливает исключение и возвращает NULL из функции.

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

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

Группа: tp_hash, tp_richcompare

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

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

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

Py_ssize_t PyTypeObject.tp_weaklistoffset

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

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

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

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

Когда тип, определённый оператором класса, не имеет объявления __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

Необязательный указатель на статический 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; это словарь атрибутов самого объекта типа.

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

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

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

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

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

Когда тип, определённый оператором класса, имеет объявление __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);

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

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

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

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

Это поле должно быть установлено в 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 для использования при вызовах этого объекта типа. Другими словами, она используется для реализации vectorcall для type.__call__. Если tp_vectorcall равно NULL, используется стандартная реализация вызова с использованием __new__() и __init__().

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

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

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

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

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

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

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

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

Типы в куче

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

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

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

Spec-Zone.ru

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