Тип объекты

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

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

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

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

«слоты tp»

PyTypeObject слот [1] Тип специальные методы/атрибуты Инфо [2]
O T D I
<R> tp_name const char * __name__ X X    
tp_basicsize Py_ssize_t   X X   X
tp_itemsize Py_ssize_t     X   X
tp_dealloc destructor   X X   X
tp_vectorcall_offset Py_ssize_t         ?
(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

Если COUNT_ALLOCS определена, то также существуют следующие поля (только для внутреннего использования):

[1]Имя слота в круглых скобках указывает на то, что оно (фактически) устарело. Имена в угловых скобках следует рассматривать как доступные только для чтения. Имена в квадратных скобках предназначены только для внутреннего пользования. «<R>» (в качестве префикса) означает, что поле является обязательным (не должно быть NULL).
[2]

Колонки:

«О»: установлен на PyBaseObject_Type

«Т»: установлен на PyType_Type

«D»: по умолчанию (если слот установлен на NULL)

X - PyType_Ready устанавливает значение, если оно равно NULL
~ - PyType_Ready всегда устанавливает это значение (оно должно быть NULL)
? - PyType_Ready может установить это значение в зависимости от других слотов

Также см. столбец наследования ("I").

«I»: наследование

X - слот типа наследуется через PyType_Ready, если определён со значением NULL
% - слоты субструктуры наследуются индивидуально
G - наследуется, но только в сочетании с другими слотами; см. описание слота
? - всё сложно; см. описание слота

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

субслоты

Слот Тип специальные методы
am_await unaryfunc __await__
am_aiter unaryfunc __aiter__
am_anext unaryfunc __anext__
 
nb_add binaryfunc __add__ __radd__
nb_inplace_add binaryfunc __iadd__
nb_subtract binaryfunc __sub__ __rsub__
nb_inplace_subtract binaryfunc __sub__
nb_multiply binaryfunc __mul__ __rmul__
nb_inplace_multiply binaryfunc __mul__
nb_remainder binaryfunc __mod__ __rmod__
nb_inplace_remainder binaryfunc __mod__
nb_divmod binaryfunc __divmod__ __rdivmod__
nb_power ternaryfunc __pow__ __rpow__
nb_inplace_power ternaryfunc __pow__
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 __lshift__
nb_rshift binaryfunc __rshift__ __rrshift__
nb_inplace_rshift binaryfunc __rshift__
nb_and binaryfunc __and__ __rand__
nb_inplace_and binaryfunc __and__
nb_xor binaryfunc __xor__ __rxor__
nb_inplace_xor binaryfunc __xor__
nb_or binaryfunc __or__ __ror__
nb_inplace_or binaryfunc __or__
nb_int unaryfunc __int__
nb_reserved void *  
nb_float unaryfunc __float__
nb_floor_divide binaryfunc __floordiv__
nb_inplace_floor_divide binaryfunc __floordiv__
nb_true_divide binaryfunc __truediv__
nb_inplace_true_divide binaryfunc __truediv__
nb_index unaryfunc __index__
nb_matrix_multiply binaryfunc __matmul__ __rmatmul__
nb_inplace_matrix_multiply binaryfunc __matmul__
 
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()  

слоты typedefs

typedef Типы параметров Возвращаемый тип
allocfunc
Py_ssize_t
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
Py_ssize_t
PyObject *
ssizeobjargproc
Py_ssize_t
int
objobjproc int
objobjargproc int

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

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

Определение структуры для 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)
                                    or 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; /* Строка документации */

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

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

    /* богатые сравнения */
    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;

} PyTypeObject;

Слоты PyObject

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

PyObject* PyObject._ob_next
PyObject * PyObject._ob_prev

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

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

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

Py_ssize_t PyObject.ob_refcnt

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

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

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

PyTypeObject* PyObject.ob_type

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

Foo_Type.ob_type = &PyType_Type;

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

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

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

Слоты PyVarObject

Py_ssize_t PyVarObject.ob_size

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

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

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

Слоты PyTypeObject

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

const char* PyTypeObject.tp_name

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

Для динамически выделяемых объектов типа это должно быть просто имя типа, а имя модуля, явно сохраненное в типе dict как значение для ключа '__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_VarNew(), или PyObject_GC_Del(), если экземпляр был выделен с использованием PyObject_GC_New() или PyObject_GC_NewVar().

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

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. Сигнатура такая же, как у _PyObject_Vectorcall():

PyObject *vectorcallfunc(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)

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

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

PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)

Вызвать vectorcallfunc callable с позиционными аргументами и ключевыми аргументами, указанными в кортеже и dict, соответственно.

Данная функция предназначена для использования в слоте tp_call. Она не возвращается к tp_call и в настоящее время не проверяет флаг _Py_TPFLAGS_HAVE_VECTORCALL. Чтобы вызвать объект, использовать вместо неё одну из функций PyObject_Call.

Примечание

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

Примечание

Семантика слота tp_vectorcall_offset является предварительной и ожидается, что она будет завершена в Python 3.9. Если вы используете vectorcall, запланировать обновление кода для Python 3.9.

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

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

Данное поле наследуется подтипами вместе с tp_call: подтип наследует tp_vectorcall_offset от своего базового типа, когда tp_call подтипа — NULL.

Обратите внимание, что типы кучи (включая подклассы, определённые в Python) не наследуют флаг _Py_TPFLAGS_HAVE_VECTORCALL.

getattrfunc PyTypeObject.tp_getattr

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

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

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

Группа: tp_getattr, tp_getattro

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

setattrfunc PyTypeObject.tp_setattr

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

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

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

Группа: tp_setattr, tp_setattro

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

PyAsyncMethods* PyTypeObject.tp_as_async

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

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

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

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

reprfunc PyTypeObject.tp_repr

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

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

PyObject *tp_repr(PyObject *self);

Функция должна возвращать строку или Юникод объект. В идеале функция должна возвращать строку, которая при передаче в 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);

Функция должна возвращать строку или Юникод объект. Это должно быть «дружественное» строковое представление объекта, поскольку это представление будет использоваться, среди прочего, функцией 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():

PyObject *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«ed, когда создается новый экземпляр, и DECREF»ed, когда экземпляр уничтожается (это не относится к экземплярам подтипы; только тип, на который ссылается экземпляр ob_type, получает INCREF«ed или DECREF»ed).

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

???

Py_TPFLAGS_BASETYPE

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

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

???

Py_TPFLAGS_READY

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

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

???

Py_TPFLAGS_READYING

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

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

???

Py_TPFLAGS_HAVE_GC

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

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

Группа: 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_HAVE_VERSION_TAG.

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

???

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.

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

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

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

Данный бит устанавливается для static подтипа, если tp_flags не переопределен: подтип наследует _Py_TPFLAGS_HAVE_VECTORCALL от своего базового типа, когда tp_call подтипа — NULL, а Py_TPFLAGS_HEAPTYPE подтипа не установлен.

Типы кучи не наследуют _Py_TPFLAGS_HAVE_VECTORCALL.

Примечание

Данный флаг является временным и ожидается, что он станет общедоступным в Python 3.9 с другим именем и, возможно, с изменённой семантикой. Если вы используете vectorcall, запланируйте обновление кода для Python 3.9.

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

const char* PyTypeObject.tp_doc

Необязательный указатель на строку C с завершающим NUL, дающую строку документации для этого типа объекта. Он отображается как атрибут __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_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(), поскольку очистка ссылок является деликатным процессом: ссылка на содержащийся объект не должна уменьшаться до тех пор, пока указатель на содержащийся объект не будет установлен на NULL. Это связано с тем, что уменьшение счётчика ссылок может привести к тому, что содержащийся объект станет мусором, запустив цепочку действий по восстановлению, которая может включать вызов произвольного кода Python (из-за финализаторов или обратных вызовов weakref, связанных с содержащимся объектом). Если такой код может снова ссылаться на self, важно, чтобы указатель на содержащийся объект был в это время NULL, чтобы self знал, что содержащийся объект больше не может использоваться. Макрос Py_CLEAR() выполняет операции в безопасном порядке.

Поскольку цель функций 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 должен быть установлен в функции init модуля расширения.

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

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

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

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

PyObject* PyTypeObject.tp_dict

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

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

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

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

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

Если это поле NULL, PyType_Ready() назначит ему новый словарь.

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

Небезопасно использовать PyDict_SetItem() или иным образом изменять tp_dict с помощью словаря C-API.

descrgetfunc PyTypeObject.tp_descr_get

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

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

PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);

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

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

descrsetfunc PyTypeObject.tp_descr_set

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

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

int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);

Аргумент value устанавливается в NULL, чтобы удалить значение.

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

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

Py_ssize_t PyTypeObject.tp_dictoffset

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

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

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

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

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

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

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

Данное поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить это смещение; это означает, что экземпляры подтипа хранят словарь с разницей в смещении, чем базовый тип. Поскольку словарь всегда находится через 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);

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

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

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

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

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

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

PyObject* PyTypeObject.tp_mro

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

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

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

PyObject* PyTypeObject.tp_cache

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

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

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

PyObject* PyTypeObject.tp_subclasses

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

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

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

PyObject* PyTypeObject.tp_weaklist

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

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

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

destructor PyTypeObject.tp_del

Данное поле устарело. Вместо него используйте tp_finalize.

unsigned int PyTypeObject.tp_version_tag

Используется для индексации в кеш-памяти методов. Только для внутреннего пользования.

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

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

destructor PyTypeObject.tp_finalize

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

void tp_finalize(PyObject *self);

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

tp_finalize не должен изменять текущий статус исключения; поэтому рекомендуемый способ написать нетривиальный финализатор:

static void
local_finalize(PyObject *self)
{
    PyObject *error_type, *error_value, *error_traceback;

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

    /* ... */

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

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

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

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

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

См.также

«Safe object finalization» (PEP 442)

Остальные поля определяются только в том случае, если определён макрос проверки функций COUNT_ALLOCS, и предназначены только для внутреннего использования. Они задокументированы здесь для полноты. Ни одно из этих полей не наследуется подтипами.

Py_ssize_t PyTypeObject.tp_allocs

Количество размещений.

Py_ssize_t PyTypeObject.tp_frees

Количество фризов.

Py_ssize_t PyTypeObject.tp_maxalloc

Максимум одновременно размещаемых объектов.

PyTypeObject* PyTypeObject.tp_prev

Указатель на объект предыдущего типа с ненулевым полем tp_allocs.

PyTypeObject* PyTypeObject.tp_next

Указатель на объект следующего типа с ненулевым полем tp_allocs.

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

Типы кучи

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

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

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

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

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

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

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

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

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

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

Структуры объектов последовательности

PySequenceMethods

Данная структура содержит указатели на функции, которые объект использует для реализации протокола последовательности.

lenfunc PySequenceMethods.sq_length

Данная функция используется PySequence_Size() и PyObject_Size() и с той же сигнатурой. Она также используется для обработки отрицательных индексов через слоты sq_item и sq_ass_item.

binaryfunc PySequenceMethods.sq_concat

Данная функция используется PySequence_Concat() и с такой же сигнатурой. Она также используется оператором + после попытки сложения чисел через слот nb_add.

ssizeargfunc PySequenceMethods.sq_repeat

Данная функция используется PySequence_Repeat() и с такой же сигнатурой. Она также используется оператором * после попытки числового умножения через слот nb_multiply.

ssizeargfunc PySequenceMethods.sq_item

Данная функция используется PySequence_GetItem() и с такой же сигнатурой. Она также используется PyObject_GetItem() после попытки подписки через слот mp_subscript. Данный слот должен быть заполнен, чтобы функция PySequence_Check() возвращала 1, в противном случае это может быть NULL.

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

ssizeobjargproc PySequenceMethods.sq_ass_item

Данная функция используется PySequence_SetItem() и с такой же сигнатурой. Она также используется PyObject_SetItem() и PyObject_DelItem() после попытки назначения и удаления элемента через слот mp_ass_subscript. Данный слот можно оставить NULL, если объект не поддерживает назначение и удаление элементов.

objobjproc PySequenceMethods.sq_contains

Данная функция может использоваться PySequence_Contains() и с такой же сигнатурой. Данный слот можно оставить NULL, в этом случае PySequence_Contains() просто просматривает последовательность, пока не найдет совпадение.

binaryfunc PySequenceMethods.sq_inplace_concat

Данная функция используется PySequence_InPlaceConcat() и с такой же сигнатурой. Она должна изменить свой первый операнд и вернуть его. Данный слот можно оставить NULL, в этом случае PySequence_InPlaceConcat() вернётся к PySequence_Concat(). Он также используется расширенным назначением += после попытки числового сложения на месте через слот nb_inplace_add.

ssizeargfunc PySequenceMethods.sq_inplace_repeat

Данная функция используется PySequence_InPlaceRepeat() и с такой же сигнатурой. Она должна изменить свой первый операнд и вернуть его. Данный слот можно оставить NULL, в этом случае PySequence_InPlaceRepeat() вернётся к PySequence_Repeat(). Он также используется расширенным назначением *= после попытки числового умножения на месте через слот nb_inplace_multiply.

Структуры буферных объектов

PyBufferProcs

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

getbufferproc PyBufferProcs.bf_getbuffer

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

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

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

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

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

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

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

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

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

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

releasebufferproc PyBufferProcs.bf_releasebuffer

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

void (PyObject *exporter, Py_buffer *view);

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

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

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

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

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

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

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

PyAsyncMethods

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

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

typedef struct {
    unaryfunc am_await;
    unaryfunc am_aiter;
    unaryfunc am_anext;
} 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.

Тип слота typedefs

PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)

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

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

void (*destructor)(PyObject *)
PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)

См. tp_vectorcall_offset.

Аргументы для vectorcallfunc такие же, как для _PyObject_Vectorcall().

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

void (*freefunc)(void *)

См. tp_free.

PyObject *(*newfunc)(PyObject *, PyObject *, PyObject *)

См. tp_new.

int (*initproc)(PyObject *, PyObject *, PyObject *)

См. tp_init.

PyObject *(*reprfunc)(PyObject *)

См. tp_repr.

PyObject *(*getattrfunc)(PyObject *self, char *attr)

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

int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)

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

PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)

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

См. tp_getattro.

int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)

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

См. tp_setattro.

PyObject *(*descrgetfunc)(PyObject *, PyObject *, PyObject *)

См. tp_descrget.

int (*descrsetfunc)(PyObject *, PyObject *, PyObject *)

См. tp_descrset.

Py_hash_t (*hashfunc)(PyObject *)

См. tp_hash.

PyObject *(*richcmpfunc)(PyObject *, PyObject *, int)

См. tp_richcompare.

PyObject *(*getiterfunc)(PyObject *)

См. tp_iter.

PyObject *(*iternextfunc)(PyObject *)

См. tp_iternext.

Py_ssize_t (*lenfunc)(PyObject *)
int (*getbufferproc)(PyObject *, Py_buffer *, int)
void (*releasebufferproc)(PyObject *, Py_buffer *)
PyObject *(*unaryfunc)(PyObject *)
PyObject *(*binaryfunc)(PyObject *, PyObject *)
PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *)
PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t)
int (*ssizeobjargproc)(PyObject *, Py_ssize_t)
int (*objobjproc)(PyObject *, PyObject *)
int (*objobjargproc)(PyObject *, PyObject *, PyObject *)

Примеры

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

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

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

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = "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 */
    "My objects",                   /* tp_doc */
    0,                              /* tp_traverse */
    0,                              /* tp_clear */
    0,                              /* tp_richcompare */
    0,                              /* tp_weaklistoffset */
    0,                              /* tp_iter */
    0,                              /* tp_iternext */
    0,                              /* tp_methods */
    0,                              /* tp_members */
    0,                              /* tp_getset */
    0,                              /* tp_base */
    0,                              /* tp_dict */
    0,                              /* tp_descr_get */
    0,                              /* tp_descr_set */
    0,                              /* tp_dictoffset */
    0,                              /* tp_init */
    0,                              /* tp_alloc */
    myobj_new,                      /* tp_new */
};

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

typedef struct {
    PyObject_HEAD
    const char *data;
    PyObject *inst_dict;
    PyObject *weakreflist;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = "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, который не может быть разделен на подклассы и не может быть вызван для создания экземпляров (например, использует отдельную фабричную функцию):

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

static PyTypeObject MyStr_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyStr",
    .tp_basicsize = sizeof(MyStr),
    .tp_base = NULL,  // set to &PyUnicode_Type in module init
    .tp_doc = "my custom str",
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = NULL,
    .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 *),
};