Объекты типа

Возможно, одной из важнейших структур 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]

Колонки:

«O»: установка на PyBaseObject_Type

«T»: установка на 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; /* 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 */

    /* call function for all accessible objects */
    traverseproc tp_traverse;

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

    /* 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;
    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;

} PyTypeObject;

Слоты PyObject

Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (создается type_new(), обычно вызывается из инструкции class). Обратите внимание, что 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

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

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

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

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

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

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

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

Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize

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

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

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

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

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

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

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

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

destructor PyTypeObject.tp_dealloc

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

void tp_dealloc(PyObject *self);

Функция деструктора вызывается макросами Py_DECREF() и Py_XDECREF(), когда количество новых ссылок равно нулю. На данный момент сущность все еще существует, но ссылок на нее нет. Функция деструктора должна освободить все ссылки, которыми владеет сущность, освободить все буферы памяти, принадлежащие сущности (используя функцию освобождения, соответствующую функции распределения используются для аллокация буфера), и вызвать функцию tp_free типа. Если тип не является подтипируемым (не имеет установленного бита флага Py_TPFLAGS_BASETYPE), разрешается вызывать деаллокатор объекта напрямую, а не через tp_free. Деаллокатор объекта должен использоваться для аллокации сущности; обычно это PyObject_Del(), если сущность была аллоцирована с использованием PyObject_New() или PyObject_VarNew(), или PyObject_GC_Del() если сущность была аллоцирована с использованием PyObject_GC_New() или PyObject_GC_NewVar().

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

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

Примечание

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

Примечание

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

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

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

Это поле наследуется подтипами вместе с tp_call: подтип наследует tp_vectorcall_offset от своего базового типа при NULL tp_call подтипа.

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

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

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

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

???

Py_TPFLAGS_BASETYPE

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

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

???

Py_TPFLAGS_READY

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

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

???

Py_TPFLAGS_READYING

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

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

???

Py_TPFLAGS_HAVE_GC

Бит устанавливается, когда объект поддерживает сбор мусора. Если этот бит установлен, сущности должны быть созданы с помощью PyObject_GC_New() и уничтожены с помощью PyObject_GC_Del(). Подробнее в разделе Поддержка циклической сборки мусора. Бит также подразумевает, что связанные с 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.

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

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

Счетчик ссылок возвращаемого значения правильно увеличивается.

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

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

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

Группа: tp_hash, tp_richcompare

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

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

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

Py_ssize_t PyTypeObject.tp_weaklistoffset

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

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

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

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

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

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

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

getiterfunc PyTypeObject.tp_iter

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

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

PyObject *tp_iter(PyObject *self);

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

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

iternextfunc PyTypeObject.tp_iternext

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

PyObject *tp_iternext(PyObject *self);

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

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

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

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

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

struct PyMethodDef* PyTypeObject.tp_methods

Необязательный указатель на статический 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

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

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

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

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

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

descrsetfunc PyTypeObject.tp_descr_set

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

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

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

Аргумент value имеет значение NULL для удаления значения.

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

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

Py_ssize_t PyTypeObject.tp_dictoffset

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

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

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

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

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

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

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

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

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

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

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

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

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

initproc PyTypeObject.tp_init

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

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

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

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

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

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

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

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

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

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

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

allocfunc PyTypeObject.tp_alloc

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

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

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

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

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

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

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

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

newfunc PyTypeObject.tp_new

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

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

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

Аргумент подтипа - это тип создаваемого объекта; аргументы 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().

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

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

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

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

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

inquiry PyTypeObject.tp_is_gc

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

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

int tp_is_gc(PyObject *self);

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

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

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

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

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

PyObject* PyTypeObject.tp_bases

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

Значение задается для типов, созданных инструкцией class. Оно должено быть NULL для статически определенных типов.

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

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

PyObject* PyTypeObject.tp_mro

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

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

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

PyObject* PyTypeObject.tp_cache

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

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

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

PyObject* PyTypeObject.tp_subclasses

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

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

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

PyObject* PyTypeObject.tp_weaklist

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

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

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

destructor PyTypeObject.tp_del

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

unsigned int PyTypeObject.tp_version_tag

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

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

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

destructor PyTypeObject.tp_finalize

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

void tp_finalize(PyObject *self);

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

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

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

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

    /* ... */

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

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

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

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

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

См.также

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

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

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 коде, являются статическими, то есть статическая структура 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

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

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

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, если объект не является awaitable.

unaryfunc PyAsyncMethods.am_aiter

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

PyObject *am_aiter(PyObject *self);

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

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

unaryfunc PyAsyncMethods.am_anext

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

PyObject *am_anext(PyObject *self);

Должна возвращать awaitable объект. Дополнительные сведения см. в разделе __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 для удаления атрибутg.

Смотрите 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 */
};

Тип, поддерживающий слабые ссылки, сущности словари и хеширование:

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