Структуры объектов типов
Пожалуй, одна из важнейших структур в системе объектов Python — структура, определяющая новый тип: структура PyTypeObject. Объекты типов можно обрабатывать с помощью любой из функций PyObject_* или PyType_*, но для большинства приложений Python они не предлагают ничего особенно интересного. Эти объекты лежат в основе поведения объектов, поэтому они очень важны для самого интерпретатора и для любого модуля расширения, реализующего новые типы.
Объекты типов довольно велики по сравнению с большинством стандартных типов. Их размер обусловлен тем, что каждый объект типа хранит большое количество значений, преимущественно указателей на функции C, каждый из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно рассматриваются в этом разделе. Поля описаны в порядке их расположения в структуре.
Помимо следующей краткой справки, раздел Примеры даёт наглядное представление о значении и использовании PyTypeObject.
Краткая справка
«слоты tp»
Слот PyTypeObject [1] | специальные методы/атрибуты | Информация [2] | ||||
|---|---|---|---|---|---|---|
O | T | D | I | |||
<R> | const char * | __name__ | X | X | ||
X | X | X | ||||
X | X | |||||
X | X | X | ||||
X | X | |||||
__getattribute__, __getattr__ | G | |||||
__setattr__, __delattr__ | G | |||||
% | ||||||
__repr__ | X | X | X | |||
% | ||||||
% | ||||||
% | ||||||
__hash__ | X | G | ||||
__call__ | X | X | ||||
__str__ | X | X | ||||
__getattribute__, __getattr__ | X | X | G | |||
__setattr__, __delattr__ | X | X | G | |||
% | ||||||
unsigned long | X | X | ? | |||
const char * | __doc__ | X | X | |||
X | G | |||||
X | G | |||||
__lt__, __le__, __eq__, __ne__, __gt__, __ge__ | X | G | ||||
X | ? | |||||
__iter__ | X | |||||
__next__ | X | |||||
| X | X | ||||
| X | |||||
| X | X | ||||
__base__ | X | |||||
| __dict__ | ? | ||||
__get__ | X | |||||
__set__, __delete__ | X | |||||
X | ? | |||||
__init__ | X | X | X | |||
X | ? | ? | ||||
__new__ | X | X | ? | ? | ||
X | X | ? | ? | |||
X | X | |||||
< |
| __bases__ | ~ | |||
< |
| __mro__ | ~ | |||
[ |
| |||||
void * | __subclasses__ | |||||
| ||||||
( | ||||||
unsigned int | ||||||
__del__ | X | |||||
unsigned char | ||||||
подслоты
Слот | специальные методы | |
|---|---|---|
__await__ | ||
__aiter__ | ||
__anext__ | ||
__add__ __radd__ | ||
__iadd__ | ||
__sub__ __rsub__ | ||
__isub__ | ||
__mul__ __rmul__ | ||
__imul__ | ||
__mod__ __rmod__ | ||
__imod__ | ||
__divmod__ __rdivmod__ | ||
__pow__ __rpow__ | ||
__ipow__ | ||
__neg__ | ||
__pos__ | ||
__abs__ | ||
__bool__ | ||
__invert__ | ||
__lshift__ __rlshift__ | ||
__ilshift__ | ||
__rshift__ __rrshift__ | ||
__irshift__ | ||
__and__ __rand__ | ||
__iand__ | ||
__xor__ __rxor__ | ||
__ixor__ | ||
__or__ __ror__ | ||
__ior__ | ||
__int__ | ||
void * | ||
__float__ | ||
__floordiv__ | ||
__ifloordiv__ | ||
__truediv__ | ||
__itruediv__ | ||
__index__ | ||
__matmul__ __rmatmul__ | ||
__imatmul__ | ||
__len__ | ||
__getitem__ | ||
__setitem__, __delitem__ | ||
__len__ | ||
__add__ | ||
__mul__ | ||
__getitem__ | ||
__setitem__ __delitem__ | ||
__contains__ | ||
__iadd__ | ||
__imul__ | ||
__buffer__ | ||
__release_buffer__ | ||
Определения типов слотов
определение типа | Типы параметров | Тип возвращаемого значения |
|---|---|---|
| ||
| void | |
void * | void | |
int | ||
| ||
int | ||
|
| |
| ||
int | ||
| ||
int | ||
| ||
int | ||
| Py_hash_t | |
| ||
|
| |
|
| |
| ||
int | ||
void | ||
| int | |
| ||
| ||
| ||
| ||
int | ||
int | ||
int |
Подробнее см. ниже: Определения типов слотов.
Определение PyTypeObject
Определение структуры PyTypeObject можно найти в Include/cpython/object.h. Для удобства здесь повторено приведённое там определение:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
PyMethodDef *tp_methods;
PyMemberDef *tp_members;
PyGetSetDef *tp_getset;
// Strong reference on a heap type, borrowed reference on a static type
PyTypeObject *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; /* no longer used */
void *tp_subclasses; /* for static builtin types this is an index */
PyObject *tp_weaklist; /* not used for static builtin types */
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6.
* If zero, the cache is invalid and must be initialized.
*/
unsigned int tp_version_tag;
destructor tp_finalize;
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
unsigned char tp_watched;
/* Number of tp_version_tag values used.
* Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
* disabled for this type (e.g. due to custom MRO entries).
* Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere).
*/
uint16_t tp_versions_used;
} PyTypeObject;
Слоты PyObject
Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (создаваемых с помощью type_new(), обычно вызываемого из инструкции class). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, а значит, его экземпляры (то есть объекты типов) должны иметь поле ob_size.
Счётчик ссылок объекта типа инициализируется значением 1 макросом PyObject_HEAD_INIT. Обратите внимание, что для статически размещённых объектов типов экземпляры типа (объекты, у которых 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_SIZE().
Наследование:
Это поле не наследуется подклассами.
Слоты PyTypeObject
Для каждого слота есть раздел с описанием наследования. Если PyType_Ready() может устанавливать значение, когда поле установлено в NULL, то будет также раздел «По умолчанию». (Обратите внимание, что многие поля, установленные в PyBaseObject_Type и PyType_Type, фактически действуют как значения по умолчанию.)
-
const char *PyTypeObject.tp_name -
Указатель на завершающуюся нулевым байтом строку, содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, за которым следует точка, а затем имя типа; для встроенных типов достаточно указать только имя типа. Если модуль является подмодулем пакета, полное имя пакета входит в полное имя модуля. Например, тип с именем
T, определённый в модулеMво вложенном пакетеQпакетаP, должен иметь инициализаторtp_name"P.Q.M.T".Для динамически выделяемых объектов типа здесь следует указывать только имя типа, а имя модуля должно быть явно сохранено в словаре типа как значение для ключа
'__module__'.Для статически выделяемых объектов типа поле tp_name должно содержать точку. Всё, что находится до последней точки, становится доступным как атрибут
__module__, а всё, что находится после последней точки, — как атрибут__name__.Если точка отсутствует, всё поле
tp_nameстановится доступным как атрибут__name__, а атрибут__module__не определён (если только он явно не задан в словаре, как описано выше). Это означает, что ваш тип невозможно будет сериализовать с помощью pickle. Кроме того, он не будет указан в документации модулей, созданной с помощью pydoc.Это поле не должно быть
NULL. Это единственное обязательное поле вPyTypeObject()(помимо возможногоtp_itemsize).Наследование:
Это поле не наследуется подклассами.
-
Py_ssize_t PyTypeObject.tp_basicsize -
Py_ssize_t PyTypeObject.tp_itemsize -
Эти поля позволяют вычислить размер экземпляров типа в байтах.
Существует два вида типов: у типов с экземплярами фиксированной длины поле
tp_itemsizeравно нулю, а у типов с экземплярами переменной длины полеtp_itemsizeне равно нулю. Все экземпляры типа с экземплярами фиксированной длины имеют одинаковый размер, заданный вtp_basicsize. (Исключения из этого правила можно создавать с помощьюPyUnstable_Object_GC_NewWithExtraData().)Экземпляры типа с экземплярами переменной длины должны иметь поле
ob_size, а размер экземпляра равенtp_basicsizeплюс N, умноженное наtp_itemsize, где N — «длина» объекта.Такие функции, как
PyObject_NewVar(), принимают значение N в качестве аргумента и сохраняют его в поле экземпляраob_size. Обратите внимание, что впоследствии полеob_sizeможет использоваться для других целей. Например, экземплярыintиспользуют битыob_sizeспособом, определяемым реализацией; доступ к базовому хранилищу и его размеру следует получать с помощьюPyLong_Export().Примечание
Доступ к полю
ob_sizeследует осуществлять с помощью макросовPy_SIZE()иPy_SET_SIZE().Кроме того, наличие поля
ob_sizeв структуре экземпляра не означает, что структура экземпляра имеет переменную длину. Например, типlistимеет экземпляры фиксированной длины, однако в этих экземплярах есть полеob_size. (Как и в случае сint, не обращайтесь напрямую к полюob_sizeсписков. Вместо этого вызывайтеPyList_Size().)Поле
tp_basicsizeвключает размер, необходимый для данных типа, указанного вtp_base, а также любые дополнительные данные, необходимые каждому экземпляру.Правильный способ задать
tp_basicsize— использовать операторsizeofдля структуры, применяемой для объявления структуры экземпляра. Эта структура должна включать структуру, используемую для объявления базового типа. Иными словами,tp_basicsizeдолжно быть больше или равноtp_basicsizeбазового типа.Поскольку каждый тип является подтипом
object, эта структура должна включатьPyObjectилиPyVarObject(в зависимости от того, следует ли включатьob_size). Обычно они определяются макросамиPyObject_HEADилиPyObject_VAR_HEADсоответственно.Базовый размер не включает размер заголовка GC, поскольку этот заголовок не является частью
PyObject_HEAD.Если структура, используемая для объявления базового типа, неизвестна, см.
PyType_Spec.basicsizeиPyType_FromMetaclass().Примечания о выравнивании:
-
tp_basicsizeдолжно быть кратно_Alignof(PyObject). При использованииsizeofдляstruct, включающегоPyObject_HEAD, как и рекомендуется, компилятор обеспечивает это условие. Если Cstructне используется либо используются расширения компилятора, такие как__attribute__((packed)), обеспечить это условие должны вы. - Если для элементов переменной части требуется определённое выравнивание,
tp_basicsizeиtp_itemsizeдолжны быть кратны этому выравниванию. Например, если переменная часть типа хранитdouble, вы должны обеспечить, чтобы оба поля были кратны_Alignof(double).
Наследование:
Подтипы наследуют эти поля независимо друг от друга. (То есть, если значение поля равно нулю,
PyType_Ready()скопирует значение из базового типа, указывая, что экземплярам не требуется дополнительное хранилище.)Если значение
tp_itemsizeбазового типа не равно нулю, обычно небезопасно задаватьtp_itemsizeдругое ненулевое значение в подтипе (хотя это зависит от реализации базового типа). -
-
destructor PyTypeObject.tp_dealloc -
Соответствующий идентификатор слота
Py_tp_deallocвходит в стабильный ABI.Указатель на функцию-деструктор экземпляра. Сигнатура функции:
void tp_dealloc(PyObject *self);
Функция-деструктор должна удалить все ссылки, которыми владеет экземпляр (например, вызвать
Py_CLEAR()), освободить все буферы памяти, принадлежащие экземпляру, и вызвать функциюtp_freeтипа для освобождения самого объекта.Если вы можете вызывать функции, которые могут установить индикатор ошибки, необходимо использовать
PyErr_GetRaisedException()иPyErr_SetRaisedException(), чтобы не затереть уже установленный индикатор ошибки (освобождение могло произойти при обработке другой ошибки):static void foo_dealloc(foo_object *self) { PyObject *et, *ev, *etb; PyObject *exc = PyErr_GetRaisedException(); ... PyErr_SetRaisedException(exc); }Сам обработчик освобождения не должен возбуждать исключение; при возникновении ошибки он должен вызвать
PyErr_FormatUnraisable(), чтобы записать в журнал (и очистить) необрабатываемое исключение.Нет гарантий относительно того, когда объект будет уничтожен, за исключением следующих:
- Python уничтожит объект немедленно или спустя некоторое время после удаления последней ссылки на него, если только его финализатор (
tp_finalize) впоследствии не воскресит объект. - Объект не будет уничтожен во время автоматической финализации (
tp_finalize) или автоматической очистки (tp_clear).
В настоящее время CPython уничтожает объект непосредственно из
Py_DECREF(), когда новое значение счётчика ссылок равно нулю, однако в будущей версии это может измениться.Рекомендуется вызывать
PyObject_CallFinalizerFromDealloc()в началеtp_dealloc, чтобы гарантировать финализацию объекта перед его уничтожением.Если тип поддерживает сборку мусора (установлен флаг
Py_TPFLAGS_HAVE_GC), перед очисткой полей-членов деструктор должен вызватьPyObject_GC_UnTrack().Допускается вызывать
tp_clearизtp_dealloc, чтобы избежать дублирования кода и гарантировать очистку объекта перед его уничтожением. Учтите, чтоtp_clearуже могла быть вызвана.Если тип размещён в куче (
Py_TPFLAGS_HEAPTYPE), после вызова деаллокатора типа деаллокатор должен освободить принадлежащую ему ссылку на объект типа (с помощьюPy_DECREF()). См. пример кода ниже:static void foo_dealloc(PyObject *op) { foo_object *self = (foo_object *) op; PyObject_GC_UnTrack(self); Py_CLEAR(self->ref); Py_TYPE(self)->tp_free(self); }tp_deallocдолжна оставить состояние исключения неизменным. Если ей необходимо вызвать функцию, которая может возбудить исключение, сначала следует сохранить состояние исключения, а затем восстановить его (после записи любых исключений в журнал с помощьюPyErr_WriteUnraisable()).Пример:
static void foo_dealloc(PyObject *self) { PyObject *exc = PyErr_GetRaisedException(); if (PyObject_CallFinalizerFromDealloc(self) < 0) { // self was resurrected. goto done; } PyTypeObject *tp = Py_TYPE(self); if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) { PyObject_GC_UnTrack(self); } // Optional, but convenient to avoid code duplication. if (tp->tp_clear && tp->tp_clear(self) < 0) { PyErr_WriteUnraisable(self); } // Any additional destruction goes here. tp->tp_free(self); self = NULL; // In case PyErr_WriteUnraisable() is called below. if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_CLEAR(tp); } done: // Optional, if something was called that might have raised an // exception. if (PyErr_Occurred()) { PyErr_WriteUnraisable(self); } PyErr_SetRaisedException(exc); }tp_deallocможет быть вызвана из любого потока Python, а не только из потока, создавшего объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Для вызовов Python API это не проблема, поскольку поток, в котором вызываетсяtp_dealloc, имеет присоединённое состояние потока. Однако если уничтожаемый объект, в свою очередь, уничтожает объекты из другой библиотеки C, необходимо убедиться, что уничтожение этих объектов в потоке, вызвавшемtp_dealloc, не нарушит предположений библиотеки.Наследование:
Это поле наследуется подклассами.
См. также
Подробные сведения о связи этого слота с другими слотами см. в разделе Жизненный цикл объекта.
- Python уничтожит объект немедленно или спустя некоторое время после удаления последней ссылки на него, если только его финализатор (
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset -
Необязательное смещение до функции для отдельного экземпляра, реализующей вызов объекта с использованием протокола vectorcall — более эффективной альтернативы простому
tp_call.Это поле используется только в том случае, если установлен флаг
Py_TPFLAGS_HAVE_VECTORCALL. Если он установлен, поле должно содержать положительное целое число — смещение в экземпляре указателяvectorcallfunc.Указатель vectorcallfunc может быть
NULL; в этом случае экземпляр ведёт себя так, как если быPy_TPFLAGS_HAVE_VECTORCALLне был установлен: при вызове экземпляра используетсяtp_call.Любой класс, задающий
Py_TPFLAGS_HAVE_VECTORCALL, должен также задаватьtp_callи обеспечивать согласованность его поведения с функцией vectorcallfunc. Для этого можно присвоить tp_call значениеPyVectorcall_Call().Изменено в версии 3.8: До версии 3.8 этот слот назывался
tp_print. В Python 2.x он использовался для вывода в файл. В Python 3.0–3.7 он не использовался.Изменено в версии 3.12: До версии 3.12 не рекомендовалось реализовывать протокол vectorcall для изменяемых типов в куче. Когда пользователь задаёт
__call__в коде Python, обновляется только tp_call, что, вероятно, приводит к его несогласованности с функцией vectorcall. Начиная с версии 3.12, задание__call__отключает оптимизацию vectorcall, сбрасывая флагPy_TPFLAGS_HAVE_VECTORCALL.Наследование:
Это поле всегда наследуется. Однако флаг
Py_TPFLAGS_HAVE_VECTORCALLнаследуется не всегда. Если он не установлен, подкласс не будет использовать vectorcall, за исключением случаев явного вызоваPyVectorcall_Call().
-
getattrfunc PyTypeObject.tp_getattr -
Соответствующий идентификатор слота
Py_tp_getattrвходит в стабильный ABI.Необязательный указатель на функцию получения атрибута по строке.
Это поле объявлено устаревшим. Если оно задано, оно должно указывать на функцию, действующую так же, как функция
tp_getattro, но принимающую строку C вместо строкового объекта Python для указания имени атрибута.Наследование:
Группа:
tp_getattr,tp_getattroЭто поле наследуется подклассами вместе с
tp_getattro: подкласс наследует иtp_getattr, иtp_getattroот базового типа, еслиtp_getattrиtp_getattroподкласса имеют значениеNULL.
-
setattrfunc PyTypeObject.tp_setattr -
Соответствующий идентификатор слота
Py_tp_setattrвходит в стабильный ABI.Необязательный указатель на функцию установки и удаления атрибутов.
Это поле объявлено устаревшим. Если оно задано, оно должно указывать на функцию, действующую так же, как функция
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 -
Соответствующий идентификатор слота
Py_tp_reprвходит в стабильный ABI.Необязательный указатель на функцию, реализующую встроенную функцию
repr().Сигнатура совпадает с сигнатурой
PyObject_Repr():PyObject *tp_repr(PyObject *self);
Функция должна возвращать строку или объект Unicode. В идеале эта функция должна возвращать строку, передача которой в
eval()в подходящем окружении возвращает объект с тем же значением. Если это невозможно, функция должна возвращать строку, начинающуюся с'<'и заканчивающуюся'>', по которой можно определить тип и значение объекта.Наследование:
Это поле наследуется подклассами.
Значение по умолчанию:
Если это поле не задано, возвращается строка вида
<%s object at %p>, где%sзаменяется именем типа, а%p— адресом объекта в памяти.
-
PyNumberMethods *PyTypeObject.tp_as_number -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим числовой протокол. Эти поля описаны в разделе Структуры числовых объектов.
Наследование:
Поле
tp_as_numberне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
PySequenceMethods *PyTypeObject.tp_as_sequence -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим протокол последовательностей. Эти поля описаны в разделе Структуры объектов-последовательностей.
Наследование:
Поле
tp_as_sequenceне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
PyMappingMethods *PyTypeObject.tp_as_mapping -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим протокол отображений. Эти поля описаны в разделе Структуры объектов-отображений.
Наследование:
Поле
tp_as_mappingне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
hashfunc PyTypeObject.tp_hash -
Соответствующий идентификатор слота
Py_tp_hashвходит в состав стабильного ABI.Необязательный указатель на функцию, реализующую встроенную функцию
hash().Сигнатура совпадает с сигнатурой
PyObject_Hash():Py_hash_t tp_hash(PyObject *);
Значение
-1не должно возвращаться как обычное возвращаемое значение; если при вычислении хеш-значения возникает ошибка, функция должна установить исключение и вернуть-1.Если это поле не задано (и не задано
tp_richcompare), попытка вычислить хеш объекта вызывает исключениеTypeError. Это равносильно присваиванию ему значенияPyObject_HashNotImplemented().Этому полю можно явно присвоить значение
PyObject_HashNotImplemented(), чтобы запретить наследование метода хеширования от родительского типа. На уровне Python это интерпретируется как эквивалент__hash__ = None, в результате чего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.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericHash().
-
ternaryfunc PyTypeObject.tp_call -
Соответствующий идентификатор слота
Py_tp_callвходит в состав стабильного ABI.Необязательный указатель на функцию, реализующую вызов объекта. Если объект не является вызываемым, здесь должно быть
NULL. Сигнатура совпадает с сигнатуройPyObject_Call():PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);
Наследование:
Это поле наследуется подтипами.
-
reprfunc PyTypeObject.tp_str -
Соответствующий идентификатор слота
Py_tp_strвходит в состав стабильного ABI.Необязательный указатель на функцию, реализующую встроенную операцию
str(). (Обратите внимание, что теперьstr— это тип, аstr()вызывает конструктор этого типа. Этот конструктор вызываетPyObject_Str()для выполнения фактической работы, аPyObject_Str()вызывает этот обработчик.)Сигнатура совпадает с сигнатурой
PyObject_Str():PyObject *tp_str(PyObject *self);
Функция должна возвращать строку или объект Unicode. Она должна возвращать «понятное» строковое представление объекта, поскольку это представление используется, помимо прочего, функцией
print().Наследование:
Это поле наследуется подтипами.
По умолчанию:
Если это поле не задано, для возврата строкового представления вызывается
PyObject_Repr().
-
getattrofunc PyTypeObject.tp_getattro -
Соответствующий идентификатор слота
Py_tp_getattroвходит в состав стабильного ABI.Необязательный указатель на функцию получения атрибута.
Сигнатура совпадает с сигнатурой
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 -
Соответствующий идентификатор слота
Py_tp_setattroвходит в состав стабильного ABI.Необязательный указатель на функцию установки и удаления атрибутов.
Сигнатура совпадает с сигнатурой
PyObject_SetAttr():int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
Кроме того, должна поддерживаться передача
NULLв качестве значения value для удаления атрибута. Обычно удобно присвоить этому полю значениеPyObject_GenericSetAttr(), реализующее стандартный способ установки атрибутов объекта.Наследование:
Группа:
tp_setattr,tp_setattroЭто поле наследуется подтипами вместе с
tp_setattr: подтип наследует оба поля —tp_setattrиtp_setattro— от базового типа, еслиtp_setattrиtp_setattroподтипа равныNULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericSetAttr().
-
PyBufferProcs *PyTypeObject.tp_as_buffer -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим буферный интерфейс. Эти поля описаны в разделе Структуры буферных объектов.
Наследование:
Поле
tp_as_bufferне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
unsigned long PyTypeObject.tp_flags -
Это поле представляет собой битовую маску различных флагов. Некоторые флаги указывают на варианты семантики в определённых ситуациях; другие используются для указания того, что определённые поля объекта типа (или в структурах расширения, на которые ссылаются через
tp_as_number,tp_as_sequence,tp_as_mappingиtp_as_buffer), которые исторически присутствовали не всегда, являются допустимыми; если соответствующий бит флага сброшен, поля типа, за доступ к которым он отвечает, нельзя использовать, и вместо этого их следует считать имеющими нулевое илиNULLзначение.Наследование:
Наследование этого поля устроено сложно. Большинство битов флагов наследуются по отдельности, то есть если бит флага установлен у базового типа, подтип наследует этот бит. Биты флагов, относящиеся к структурам расширения, наследуются строго вместе со структурой расширения: значение бита флага базового типа копируется в подтип вместе с указателем на структуру расширения. Бит флага
Py_TPFLAGS_HAVE_GCнаследуется вместе с полямиtp_traverseиtp_clear, то есть если бит флагаPy_TPFLAGS_HAVE_GCсброшен у подтипа, а поляtp_traverseиtp_clearу подтипа существуют и имеют значенияNULL.Значение по умолчанию:
PyBaseObject_TypeиспользуетPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.Битовые маски:
В настоящее время определены следующие битовые маски; их можно объединять оператором
|, чтобы сформировать значение поляtp_flags. МакросPyType_HasFeature()принимает тип и значение флагов — tp и f — и проверяет, является лиtp->tp_flags & fненулевым.-
Py_TPFLAGS_HEAPTYPE -
Этот бит устанавливается, когда сам объект типа выделен в куче, например, для типов, созданных динамически с помощью
PyType_FromSpec(). В этом случае полеob_typeего экземпляров считается ссылкой на тип, и при создании нового экземпляра для объекта типа выполняется INCREF, а при уничтожении экземпляра — DECREF (это не относится к экземплярам подтипов; INCREF или DECREF выполняется только для типа, на который ссылается ob_type экземпляра). Для типов в куче также следует поддерживать сборку мусора, поскольку они могут образовывать цикл ссылок с собственным объектом модуля.Наследование:
???
-
Py_TPFLAGS_BASETYPE -
Часть стабильного ABI.
Этот бит устанавливается, если тип можно использовать как базовый тип другого типа. Если этот бит сброшен, от типа нельзя создавать подтипы (аналогично классу «final» в Java).
Наследование:
???
-
Py_TPFLAGS_READY -
Этот бит устанавливается, когда объект типа полностью инициализирован функцией
PyType_Ready().Наследование:
???
-
Py_TPFLAGS_READYING -
Этот бит устанавливается, пока
PyType_Ready()выполняет инициализацию объекта типа.Наследование:
???
-
Py_TPFLAGS_HAVE_GC -
Часть стабильного ABI.
Этот бит устанавливается, если объект поддерживает сборку мусора. Если этот бит установлен, память для новых экземпляров (см.
tp_alloc) должна выделяться с помощьюPyObject_GC_NewилиPyType_GenericAlloc(), а освобождаться (см.tp_free) с помощьюPyObject_GC_Del(). Дополнительные сведения приведены в разделе Поддержка циклической сборки мусора.Наследование:
Группа:
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 -
Часть стабильного ABI.
Это битовая маска всех битов, относящихся к наличию определённых полей в объекте типа и его структурах расширения. В настоящее время она включает следующие биты:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.Наследование:
???
-
Py_TPFLAGS_METHOD_DESCRIPTOR -
Часть стабильного ABI начиная с версии 3.8.
Этот бит указывает, что объекты ведут себя как несвязанные методы.
Если этот флаг установлен для
type(meth), то:-
meth.__get__(obj, cls)(*args, **kwds)(при условии, чтоobjне равно None) должно быть эквивалентноmeth(obj, *args, **kwds). -
meth.__get__(None, cls)(*args, **kwds)должно быть эквивалентноmeth(*args, **kwds).
Этот флаг включает оптимизацию для типичных вызовов методов, таких как
obj.meth(): она позволяет избежать создания временного объекта «связанного метода» дляobj.meth.Добавлено в версии 3.8.
Наследование:
Этот флаг никогда не наследуется типами, у которых не установлен флаг
Py_TPFLAGS_IMMUTABLETYPE. Для типов расширения он наследуется при наследованииtp_descr_get. -
-
Py_TPFLAGS_MANAGED_DICT -
Этот бит указывает, что у экземпляров класса есть атрибут
__dict__, а память для словаря управляется виртуальной машиной.Если установлен этот флаг, следует также установить
Py_TPFLAGS_HAVE_GC.Функция обхода типа должна вызывать
PyObject_VisitManagedDict(), а его функция очистки должна вызыватьPyObject_ClearManagedDict().Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется, если только в суперклассе не задано поле
tp_dictoffset.
-
Py_TPFLAGS_MANAGED_WEAKREF -
Этот бит указывает, что на экземпляры класса должны быть возможны слабые ссылки.
Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется, если только в суперклассе не задано поле
tp_weaklistoffset.
-
Py_TPFLAGS_ITEMS_AT_END -
Часть стабильного ABI начиная с версии 3.12.
Можно использовать только с типами переменного размера, то есть с типами, у которых
tp_itemsizeне равно нулю.Указывает, что часть экземпляра этого типа переменного размера находится в конце области памяти экземпляра со смещением
Py_TYPE(obj)->tp_basicsize(которое может отличаться для каждого подкласса).При установке этого флага убедитесь, что все суперклассы используют такую же схему размещения в памяти или не имеют переменного размера. Python это не проверяет.
Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется.
-
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(), вызываютPyType_FastSubclass()с одним из этих флагов, чтобы быстро определить, является ли тип подклассом встроенного типа; такие специализированные проверки выполняются быстрее, чем общая проверка, напримерPyObject_IsInstance(). Пользовательские типы, наследующие встроенные типы, должны иметь соответствующим образом установленное полеtp_flags, иначе код, взаимодействующий с такими типами, будет вести себя по-разному в зависимости от используемой проверки.
-
Py_TPFLAGS_HAVE_FINALIZE -
Этот бит устанавливается, когда слот
tp_finalizeприсутствует в структуре типа.Добавлено в версии 3.4.
Устарело с версии 3.8: Этот флаг больше не нужен, поскольку интерпретатор предполагает, что слот
tp_finalizeвсегда присутствует в структуре типа.
-
-
Py_TPFLAGS_HAVE_VECTORCALL -
Входит в Стабильный ABI начиная с версии 3.12.
Этот бит устанавливается, когда класс реализует протокол vectorcall. Подробности см. в
tp_vectorcall_offset.Наследование:
Этот бит наследуется, если также наследуется
tp_call.Добавлено в версии 3.8: как
_Py_TPFLAGS_HAVE_VECTORCALLИзменено в версии 3.9: Переименовано в текущее имя без начального символа подчёркивания. Старое предварительное имя имеет статус нестрого устаревшего.
Изменено в версии 3.12: Теперь этот флаг удаляется у класса, если его метод
__call__()переназначается.Теперь этот флаг может наследоваться изменяемыми классами.
-
Py_TPFLAGS_IMMUTABLETYPE -
Этот бит устанавливается для неизменяемых объектов типа: атрибуты типа нельзя задавать или удалять.
PyType_Ready()автоматически устанавливает этот флаг для статических типов.Наследование:
Этот флаг не наследуется.
Добавлено в версии 3.10.
-
Py_TPFLAGS_DISALLOW_INSTANTIATION -
Запрещает создание экземпляров типа: установите
tp_newв NULL и не создавайте ключ__new__в словаре типа.Флаг необходимо установить до создания типа, а не после. Например, его нужно установить до вызова
PyType_Ready()для типа.Флаг автоматически устанавливается для статических типов, если
tp_baseравен NULL или&PyBaseObject_Type, аtp_newравен NULL.Наследование:
Этот флаг не наследуется. Однако экземпляры подклассов нельзя будет создавать, если только для них не задан ненулевой
tp_new(что возможно только через C API).Примечание
Чтобы запретить создание экземпляров самого класса, но разрешить создавать экземпляры его подклассов (например, для абстрактного базового класса), не используйте этот флаг. Вместо этого настройте
tp_newтак, чтобы он успешно выполнялся только для подклассов.Добавлено в версии 3.10.
-
Py_TPFLAGS_MAPPING -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам отображения, когда используются в качестве проверяемого объекта в блоке
match. Он автоматически устанавливается при регистрации или создании подклассаcollections.abc.Mappingи сбрасывается при регистрацииcollections.abc.Sequence.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимоисключающие; одновременное включение обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, у которых ещё не установлен
Py_TPFLAGS_SEQUENCE.См. также
PEP 634 — Структурное сопоставление с шаблоном: спецификация
Добавлено в версии 3.10.
-
Py_TPFLAGS_SEQUENCE -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам последовательностей, когда используются в качестве проверяемого объекта в блоке
match. Он автоматически устанавливается при регистрации или создании подклассаcollections.abc.Sequenceи сбрасывается при регистрацииcollections.abc.Mapping.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимоисключающие; одновременное включение обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, у которых ещё не установлен
Py_TPFLAGS_MAPPING.См. также
PEP 634 — Структурное сопоставление с шаблоном: спецификация
Добавлено в версии 3.10.
-
Py_TPFLAGS_VALID_VERSION_TAG -
Внутренний флаг. Не устанавливайте и не сбрасывайте его. Чтобы сообщить об изменении класса, вызовите
PyType_Modified()Предупреждение
Этот флаг присутствует в заголовочных файлах, но использовать его не следует. Он будет удалён в одной из будущих версий CPython
-
Py_TPFLAGS_HAVE_VERSION_TAG -
Этот макрос ничего не делает. Ранее он указывал, что поле
tp_version_tagдоступно и инициализировано.Нестрого устарел с версии 3.13.
-
Py_TPFLAGS_INLINE_VALUES -
Этот бит указывает, что экземпляры данного типа будут иметь массив «встроенных значений» (содержащий атрибуты объекта), размещённый непосредственно после конца объекта.
Для этого должен быть установлен
Py_TPFLAGS_HAVE_GC.Наследование:
Этот флаг не наследуется.
Добавлено в версии 3.13.
-
Py_TPFLAGS_IS_ABSTRACT -
Этот бит указывает, что тип является абстрактным и поэтому не может быть инстанцирован.
Наследование:
Этот флаг не наследуется.
См. также
-
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION -
Внутренний флаг. Не устанавливайте и не сбрасывайте его. Ранее это был зарезервированный флаг для использования в Stackless Python.
Предупреждение
Этот флаг присутствует в заголовочных файлах, но использовать его не следует. Он может быть удалён в одной из будущих версий CPython.
-
-
const char *PyTypeObject.tp_doc -
Соответствующий идентификатор слота
Py_tp_docвходит в Стабильный ABI.Необязательный указатель на завершаемую NUL C-строку с документацией для этого объекта типа. Она доступна как атрибут
__doc__типа и его экземпляров.Наследование:
Это поле не наследуется подклассами.
-
traverseproc PyTypeObject.tp_traverse -
Соответствующий идентификатор слота
Py_tp_traverseвходит в стабильный ABI.Необязательный указатель на функцию обхода для сборщика мусора. Он используется, только если установлен бит флага
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(PyObject *op, visitproc visit, void *arg) { localobject *self = (localobject *) op; Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }Обратите внимание, что
Py_VISIT()вызывается только для тех членов, которые могут участвовать в циклических ссылках. Хотя также имеется членself->key, он может быть толькоNULLили строкой Python и поэтому не может участвовать в циклической ссылке.С другой стороны, даже если вы знаете, что член не может участвовать в цикле, для отладки можно всё же посетить его, чтобы функция
gcмодуляget_referents()включала его в результат.Типы в куче (
Py_TPFLAGS_HEAPTYPE) должны посещать свой тип с помощью:Py_VISIT(Py_TYPE(self));
Это необходимо только начиная с Python 3.9. Для поддержки Python 3.8 и более ранних версий эту строку следует выполнять условно:
#if PY_VERSION_HEX >= 0x03090000 Py_VISIT(Py_TYPE(self)); #endifЕсли в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, функция обхода должна вызыватьPyObject_VisitManagedDict()следующим образом:PyObject_VisitManagedDict((PyObject*)self, visit, arg);
Предупреждение
При реализации
tp_traverseнеобходимо посещать только те члены, которыми экземпляр владеет (то есть имеет на них сильные ссылки). Например, если объект поддерживает слабые ссылки с помощью слотаtp_weaklist, указатель, поддерживающий связанный список (то, на что указывает tp_weaklist), не следует посещать, поскольку экземпляр напрямую не владеет слабыми ссылками на себя (список слабых ссылок нужен для работы механизма слабых ссылок, но экземпляр не имеет сильных ссылок на содержащиеся в нём элементы, так как их можно удалить, даже если экземпляр всё ещё существует).Предупреждение
Функция обхода не должна иметь побочных эффектов. Она не должна изменять счётчики ссылок каких-либо объектов Python, а также создавать или уничтожать объекты Python.
Обратите внимание, что
Py_VISIT()требует, чтобы параметры visit и arg вlocal_traverse()имели именно эти имена; не называйте их как-нибудь иначе.Экземпляры типов, размещённых в куче хранят ссылку на свой тип. Поэтому их функция обхода должна либо посещать
Py_TYPE(self), либо передавать эту обязанность, вызываяtp_traverseдругого типа, размещённого в куче (например, суперкласса, размещённого в куче). В противном случае объект типа может не быть собран сборщиком мусора.Примечание
Функция
tp_traverseможет вызываться из любого потока.Изменено в версии 3.9: Ожидается, что типы, размещённые в куче, будут посещать
Py_TYPE(self)вtp_traverse. В более ранних версиях Python из-за ошибки 40217 это может приводить к аварийному завершению работы в подклассах.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭто поле наследуется подклассами вместе с
tp_clearи битом флагаPy_TPFLAGS_HAVE_GC: бит флага,tp_traverseиtp_clearнаследуются от базового типа, если в подклассе они все равны нулю.
-
inquiry PyTypeObject.tp_clear -
Соответствующий идентификатор слота
Py_tp_clearвходит в стабильный ABI.Необязательный указатель на функцию очистки. Сигнатура:
int tp_clear(PyObject *);
Назначение этой функции — разорвать циклы ссылок, которые приводят к образованию циклически изолированной группы объектов, чтобы объекты можно было безопасно уничтожить. Очищенный объект является частично уничтоженным; он не обязан соблюдать инварианты, действующие при обычном использовании.
tp_clearне требуется удалять ссылки на объекты, которые не могут участвовать в циклах ссылок, например строки Python или целые числа Python. Однако может быть удобно очистить все ссылки и написать функцию типаtp_dealloc, вызывающуюtp_clear, чтобы избежать дублирования кода. (Имейте в виду, чтоtp_clearуже могла быть вызвана. Предпочтительнее вызывать идемпотентные функции, напримерPy_CLEAR().)Любую нетривиальную очистку следует выполнять в
tp_finalize, а не вtp_clear.Примечание
Если
tp_clearне удастся разорвать цикл ссылок, объекты в циклически изолированной группе объектов могут навсегда остаться недоступными для сборщика мусора («утечь»). См.gc.garbage.Примечание
Объекты, на которые ссылается данный объект (непосредственно или косвенно), могли быть уже очищены; их согласованное состояние не гарантируется.
Примечание
Функция
tp_clearможет быть вызвана из любого потока.Примечание
Не гарантируется, что объект будет автоматически очищен до вызова его деструктора (
tp_dealloc).Эта функция отличается от деструктора (
tp_dealloc) следующим:- Очистка объекта предназначена для удаления ссылок на другие объекты, которые могут участвовать в цикле ссылок. Назначение деструктора шире: он должен освободить все принадлежащие объекту ресурсы, включая ссылки на объекты, которые не могут участвовать в цикле ссылок (например, целые числа), а также память самого объекта (вызвав
tp_free). - При вызове
tp_clearдругие объекты всё ещё могут хранить ссылки на очищаемый объект. Поэтомуtp_clearне должна освобождать память самого объекта (tp_free). Деструктор же вызывается только при отсутствии (сильных) ссылок и поэтому должен безопасно уничтожить сам объект, освободив его память. -
tp_clearможет никогда не вызываться автоматически. Деструктор объекта, напротив, будет автоматически вызван через некоторое время после того, как объект станет недостижимым (то есть на объект не будет ссылок либо он будет членом циклически изолированной группы объектов).
Не гарантируется, когда, будет ли и как часто Python автоматически очищать объект, за исключением следующего:
- Python не будет автоматически очищать объект, если он достижим, то есть на него есть ссылка и он не является членом циклически изолированной группы объектов.
- Python не будет автоматически очищать объект, если он ещё не был автоматически финализирован (см.
tp_finalize). (Если финализатор воскресил объект, перед очисткой объект может быть финализирован повторно, а может и не быть.) - Если объект является членом циклически изолированной группы объектов, Python не будет автоматически очищать его, если какой-либо член этой группы ещё не был автоматически финализирован (
tp_finalize). - Python не будет уничтожать объект, пока не завершатся все автоматические вызовы его функции
tp_clear. Это гарантирует, что разрыв цикла ссылок не сделает указательselfнедействительным, пока ещё выполняетсяtp_clear. - Python не будет автоматически вызывать
tp_clearодновременно несколько раз.
В настоящее время CPython автоматически очищает объекты только при необходимости разорвать циклы ссылок в циклически изолированной группе объектов, однако в будущих версиях объекты могут регулярно очищаться перед уничтожением.
В совокупности все функции
tp_clearв системе должны разрывать все циклы ссылок. Это непростая задача; если вы не уверены, предоставьте функциюtp_clear. Например, тип tuple не реализует функциюtp_clear, поскольку можно доказать, что цикл ссылок не может состоять только из кортежей. Поэтому функцииtp_clearдругих типов отвечают за разрыв любых циклов, содержащих кортеж. Это не сразу очевидно, и обычно нет веских причин отказываться от реализацииtp_clear.Реализации
tp_clearдолжны сбрасывать ссылки экземпляра на те его члены, которые могут быть объектами Python, и устанавливать указатели на эти члены вNULL, как показано в следующем примере:static int local_clear(PyObject *op) { localobject *self = (localobject *) op; Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }Следует использовать макрос
Py_CLEAR(), поскольку очистка ссылок требует осторожности: ссылку на содержащийся объект нельзя освобождать (посредствомPy_DECREF()), пока указатель на содержащийся объект не будет установлен вNULL. Это связано с тем, что освобождение ссылки может привести к тому, что содержащийся объект станет мусором и запустит цепочку действий по его удалению, в которую может входить выполнение произвольного кода Python (из-за финализаторов или обратных вызовов weakref, связанных с содержащимся объектом). Если такой код может снова обратиться к self, важно, чтобы указатель на содержащийся объект к этому моменту имел значениеNULL, чтобы self знал, что содержащийся объект больше нельзя использовать. МакросPy_CLEAR()выполняет операции в безопасном порядке.Если в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, функция очистки должна вызватьPyObject_ClearManagedDict()следующим образом:PyObject_ClearManagedDict((PyObject*)self);
Дополнительные сведения о схеме сборки мусора Python приведены в разделе Поддержка обнаружения циклического мусора.
Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭто поле наследуется подтипами вместе с
tp_traverseи битом флагаPy_TPFLAGS_HAVE_GC: бит флага,tp_traverseиtp_clearнаследуются от базового типа, если все они равны нулю в подтипе.См. также
Подробнее о связи этого слота с другими слотами см. в разделе Жизненный цикл объекта.
- Очистка объекта предназначена для удаления ссылок на другие объекты, которые могут участвовать в цикле ссылок. Назначение деструктора шире: он должен освободить все принадлежащие объекту ресурсы, включая ссылки на объекты, которые не могут участвовать в цикле ссылок (например, целые числа), а также память самого объекта (вызвав
-
richcmpfunc PyTypeObject.tp_richcompare -
Соответствующий идентификатор слота
Py_tp_richcompareвходит в стабильный ABI.Необязательный указатель на функцию расширенного сравнения со следующей сигнатурой:
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 -
Хотя это поле по-прежнему поддерживается, вместо него по возможности следует использовать
Py_TPFLAGS_MANAGED_WEAKREF.Если экземпляры этого типа поддерживают слабые ссылки, значение этого поля больше нуля и содержит смещение начала списка слабых ссылок в структуре экземпляра (без учёта заголовка GC, если он есть); это смещение используется функцией
PyObject_ClearWeakRefs()и функциямиPyWeakref_*. Структура экземпляра должна включать поле типа PyObject*, инициализированное значениемNULL.Не путайте это поле с
tp_weaklist; там хранится начало списка слабых ссылок на сам объект типа.Устанавливать одновременно бит
Py_TPFLAGS_MANAGED_WEAKREFиtp_weaklistoffsetнельзя.Наследование:
Это поле наследуется подтипами, но см. правила ниже. Подтип может переопределить это смещение; это означает, что подтип использует другое начало списка слабых ссылок, чем базовый тип. Поскольку начало списка всегда определяется через
tp_weaklistoffset, проблем возникнуть не должно.Значение по умолчанию:
Если в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_WEAKREF, тоtp_weaklistoffsetбудет присвоено отрицательное значение, указывающее на то, что это поле небезопасно использовать.
-
getiterfunc PyTypeObject.tp_iter -
Соответствующий идентификатор слота
Py_tp_iterвходит в Стабильный ABI.Необязательный указатель на функцию, возвращающую итератор для объекта. Обычно его наличие означает, что экземпляры этого типа являются итерируемыми (хотя последовательности могут быть итерируемыми и без этой функции).
Эта функция имеет ту же сигнатуру, что и
PyObject_GetIter():PyObject *tp_iter(PyObject *self);
Наследование:
Это поле наследуется подтипами.
-
iternextfunc PyTypeObject.tp_iternext -
Соответствующий идентификатор слота
Py_tp_iternextвходит в Стабильный ABI.Необязательный указатель на функцию, возвращающую следующий элемент итератора. Сигнатура:
PyObject *tp_iternext(PyObject *self);
Когда итератор исчерпан, функция должна вернуть
NULL; исключениеStopIterationможет быть установлено, а может и нет. При возникновении другой ошибки функция также должна вернутьNULL. Наличие этой функции означает, что экземпляры этого типа являются итераторами.Типы итераторов также должны определять функцию
tp_iter, которая должна возвращать сам экземпляр итератора (а не новый экземпляр итератора).Эта функция имеет ту же сигнатуру, что и
PyIter_Next().Наследование:
Это поле наследуется подтипами.
-
struct PyMethodDef *PyTypeObject.tp_methods -
Соответствующий идентификатор слота
Py_tp_methodsвходит в Стабильный ABI.Необязательный указатель на статический массив структур
PyMethodDef, завершённый значениемNULL, в котором объявлены обычные методы этого типа.Для каждой записи массива в словарь типа (см.
tp_dictниже) добавляется запись, содержащая дескриптор метода.Наследование:
Это поле не наследуется подтипами (методы наследуются с помощью другого механизма).
-
struct PyMemberDef *PyTypeObject.tp_members -
Соответствующий идентификатор слота
Py_tp_membersвходит в Стабильный ABI.Необязательный указатель на статический массив структур
PyMemberDef, завершённый значениемNULL, в котором объявлены обычные элементы данных (поля или слоты) экземпляров этого типа.Для каждой записи массива в словарь типа (см.
tp_dictниже) добавляется запись, содержащая дескриптор элемента.Наследование:
Это поле не наследуется подтипами (элементы наследуются с помощью другого механизма).
-
struct PyGetSetDef *PyTypeObject.tp_getset -
Соответствующий идентификатор слота
Py_tp_getsetвходит в Стабильный ABI.Необязательный указатель на статический массив структур
PyGetSetDef, завершённый значениемNULL, в котором объявлены вычисляемые атрибуты экземпляров этого типа.Для каждой записи массива в словарь типа (см.
tp_dictниже) добавляется запись, содержащая дескриптор getset.Наследование:
Это поле не наследуется подтипами (вычисляемые атрибуты наследуются с помощью другого механизма).
-
PyTypeObject *PyTypeObject.tp_base -
Соответствующий идентификатор слота
Py_tp_baseвходит в Стабильный ABI.Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; для множественного наследования требуется динамически создать объект типа, вызвав метакласс.
Примечание
Инициализация слотов подчиняется правилам инициализации глобальных переменных. C99 требует, чтобы инициализаторы были «константами-адресами». Дизайнаторы функций, такие как
PyType_GenericNew(), с неявным преобразованием в указатель, являются допустимыми константами-адресами в C99.Однако стандарт не требует, чтобы унарный оператор «&», применённый к нестатической переменной, такой как
PyBaseObject_Type, давал константу-адрес. Компиляторы могут поддерживать это (gcc поддерживает), MSVC — нет. В этом конкретном случае оба компилятора строго соответствуют стандарту.Поэтому
tp_baseследует задавать в функции инициализации модуля расширения.Наследование:
Это поле не наследуется подтипами (что очевидно).
Значение по умолчанию:
По умолчанию это поле имеет значение
&PyBaseObject_Type(программистам на Python оно известно как типobject).
-
PyObject *PyTypeObject.tp_dict -
Словарь типа хранится здесь функцией
PyType_Ready().Обычно это поле следует инициализировать значением
NULLдо вызова PyType_Ready; его также можно инициализировать словарём с начальными атрибутами типа. После инициализации типа функциейPyType_Ready()в этот словарь можно добавлять дополнительные атрибуты типа, только если они не соответствуют перегруженным операциям (например,__add__()). После завершения инициализации типа это поле следует считать доступным только для чтения.Некоторые типы могут не хранить свой словарь в этом слоте. Для получения словаря произвольного типа используйте
PyType_GetDict().Изменено в версии 3.12: Внутренняя деталь реализации: для статических встроенных типов это значение всегда равно
NULL. Вместо этого словарь таких типов хранится вPyInterpreterState. Для получения словаря произвольного типа используйтеPyType_GetDict().Наследование:
Это поле не наследуется подтипами (хотя атрибуты, определённые в нём, наследуются с помощью другого механизма).
Значение по умолчанию:
Если значение этого поля равно
NULL, функцияPyType_Ready()присвоит ему новый словарь.Предупреждение
Использовать
PyDict_SetItem()для измененияtp_dictили каким-либо иным образом изменять его с помощью C API словарей небезопасно.
-
descrgetfunc PyTypeObject.tp_descr_get -
Соответствующий идентификатор слота
Py_tp_descr_getвходит в Стабильный ABI.Необязательный указатель на функцию получения значения дескриптора.
Сигнатура функции:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
Наследование:
Это поле наследуется подтипами.
-
descrsetfunc PyTypeObject.tp_descr_set -
Соответствующий идентификатор слота
Py_tp_descr_setвходит в Стабильный ABI.Необязательный указатель на функцию установки и удаления значения дескриптора.
Сигнатура функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Аргумент value получает значение
NULL, если значение нужно удалить.Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_dictoffset -
Хотя это поле по-прежнему поддерживается, по возможности вместо него следует использовать
Py_TPFLAGS_MANAGED_DICT.Если экземпляры этого типа имеют словарь с переменными экземпляра, это поле не равно нулю и содержит смещение словаря переменных экземпляра в экземплярах типа; это смещение используется функцией
PyObject_GenericGetAttr().Не путайте это поле с
tp_dict; это словарь атрибутов самого объекта типа.Значение задаёт смещение словаря относительно начала структуры экземпляра.
Поле
tp_dictoffsetследует считать доступным только для записи. Чтобы получить указатель на словарь, вызовитеPyObject_GenericGetDict(). ВызовPyObject_GenericGetDict()может потребовать выделения памяти для словаря, поэтому при обращении к атрибуту объекта может быть эффективнее вызватьPyObject_GetAttr().Устанавливать одновременно бит
Py_TPFLAGS_MANAGED_DICTи полеtp_dictoffsetнельзя.Наследование:
Это поле наследуется подклассами. Подкласс не должен переопределять это смещение: это может быть небезопасно, если код C попытается обратиться к словарю по прежнему смещению. Для корректной поддержки наследования используйте
Py_TPFLAGS_MANAGED_DICT.Значение по умолчанию:
У этого слота нет значения по умолчанию. Для статических типов, если поле равно
NULL, для экземпляров не создаётся__dict__.Если в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, то дляtp_dictoffsetустанавливается значение-1, указывающее, что использовать это поле небезопасно.
-
initproc PyTypeObject.tp_init -
Соответствующий идентификатор слота
Py_tp_initвходит в стабильный ABI.Необязательный указатель на функцию инициализации экземпляра.
Эта функция соответствует методу
__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 -
Соответствующий идентификатор слота
Py_tp_allocвходит в стабильный ABI.Необязательный указатель на функцию выделения памяти для экземпляра.
Сигнатура функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Статические подклассы наследуют этот слот; если он унаследован от
object, его значением будетPyType_GenericAlloc().Подклассы в куче не наследуют этот слот.
Значение по умолчанию:
Для подклассов в куче этому полю всегда присваивается значение
PyType_GenericAlloc().Статические подклассы наследуют этот слот (см. выше).
-
newfunc PyTypeObject.tp_new -
Соответствующий идентификатор слота
Py_tp_newвходит в стабильный ABI.Необязательный указатель на функцию создания экземпляра.
Сигнатура функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент subtype — это тип создаваемого объекта; аргументы args и kwds представляют позиционные и именованные аргументы вызова типа. Обратите внимание: subtype не обязательно должен совпадать с типом, чья функция
tp_newвызывается; он может быть подклассом этого типа (но не несвязанным типом).Функция
tp_newдолжна вызватьsubtype->tp_alloc(subtype, nitems), чтобы выделить память для объекта, а затем выполнить только ту дополнительную инициализацию, которая абсолютно необходима. Инициализацию, которую можно безопасно пропустить или повторить, следует выполнять в обработчикеtp_init. Как правило, для неизменяемых типов вся инициализация должна выполняться вtp_new, а для изменяемых типов большую её часть следует отложить доtp_init.Установите флаг
Py_TPFLAGS_DISALLOW_INSTANTIATION, чтобы запретить создание экземпляров типа в Python.Наследование:
Это поле наследуется подклассами, кроме статических типов, у которых
tp_baseравноNULLили&PyBaseObject_Type.Значение по умолчанию:
Для статических типов значение этого поля не задано по умолчанию. Это означает, что если для слота задано значение
NULL, тип нельзя вызвать для создания новых экземпляров; предположительно, экземпляры создаются другим способом, например с помощью фабричной функции.
-
freefunc PyTypeObject.tp_free -
Соответствующий идентификатор слота
Py_tp_freeвходит в стабильный ABI.Необязательный указатель на функцию освобождения памяти экземпляра. Её сигнатура:
void tp_free(void *self);
Эта функция должна освободить память, выделенную функцией
tp_alloc.Наследование:
Статические подклассы наследуют этот слот; если он унаследован от
object, его значением будетPyObject_Free(). Исключение: если тип поддерживает сборку мусора (то есть в полеtp_flagsустановлен флагPy_TPFLAGS_HAVE_GC) и унаследовал быPyObject_Free(), этот слот не наследуется, а вместо этого по умолчанию получает значениеPyObject_GC_Del().Подклассы в куче не наследуют этот слот.
Значение по умолчанию:
Для подклассов в куче по умолчанию используется деаллокатор, соответствующий
PyType_GenericAlloc()и значению флагаPy_TPFLAGS_HAVE_GC.Статические подклассы наследуют этот слот (см. выше).
-
inquiry PyTypeObject.tp_is_gc -
Соответствующий идентификатор слота
Py_tp_is_gcвходит в стабильный ABI.Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщику мусора нужно знать, подлежит ли конкретный объект сборке. Обычно для этого достаточно проверить поле
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 -
Соответствующий идентификатор слота
Py_tp_basesвходит в стабильный ABI.Кортеж базовых типов.
Для этого поля следует установить значение
NULLи считать его доступным только для чтения. Python заполнит его при вызовеinitializedдля типа.Для динамически создаваемых классов слот
Py_tp_basesslotможно использовать вместо аргумента bases функцииPyType_FromSpecWithBases(). Предпочтительнее использовать аргумент.Предупреждение
Множественное наследование плохо работает со статически определёнными типами. Если присвоить
tp_basesкортеж, Python не вызовет ошибку, но некоторые слоты будут унаследованы только от первого базового типа.Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_mro -
Кортеж, содержащий полный набор базовых типов: он начинается с самого типа и заканчивается
object, в порядке разрешения методов.Это поле следует устанавливать в
NULLи считать доступным только для чтения. Python заполнит его, когда тип будет готов с помощьюinitialized.Наследование:
Это поле не наследуется; его значение вычисляется заново функцией
PyType_Ready().
-
PyObject *PyTypeObject.tp_cache -
Не используется. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
void *PyTypeObject.tp_subclasses -
Коллекция подклассов. Только для внутреннего использования. Может содержать недопустимый указатель.
Чтобы получить список подклассов, вызовите метод Python
__subclasses__().Изменено в версии 3.12: У некоторых типов это поле не содержит допустимый PyObject*. Тип был изменён на void*, чтобы это обозначить.
Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_weaklist -
Голова списка слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего использования.
Изменено в версии 3.12: Подробность реализации: у встроенных статических типов это поле всегда равно
NULL, даже если добавлены слабые ссылки. Вместо этого слабые ссылки для каждого из них хранятся вPyInterpreterState. Используйте публичный C API или внутренний макрос_PyObject_GET_WEAKREFS_LISTPTR(), чтобы не учитывать это различие.Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_del -
Соответствующий идентификатор слота
Py_tp_delвходит в стабильный ABI.Это поле устарело. Вместо него используйте
tp_finalize.
-
unsigned int PyTypeObject.tp_version_tag -
Используется для индексации кэша методов. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_finalize -
Соответствующий идентификатор слота
Py_tp_finalizeвходит в стабильный ABI начиная с версии 3.5.Необязательный указатель на функцию финализации экземпляра. Это реализация на C специального метода
__del__(). Её сигнатура:void tp_finalize(PyObject *self);
Основная цель финализации — выполнить все нетривиальные операции очистки, которые необходимо провести до уничтожения объекта, пока сам объект и все объекты, на которые он прямо или косвенно ссылается, находятся в согласованном состоянии. Финализатору разрешено выполнять произвольный код Python.
До того как Python автоматически финализирует объект, некоторые прямые или косвенные объекты, на которые он ссылается, могли уже быть автоматически финализированы. Однако ни один из этих объектов ещё не был автоматически очищен (см.
tp_clear).Другие нефинализированные объекты всё ещё могут использовать финализированный объект, поэтому финализатор должен оставить объект в разумном состоянии (например, инварианты должны по-прежнему выполняться).
Примечание
После автоматической финализации объекта Python может начать автоматически очищать (см.
tp_clear) этот объект и объекты, на которые он ссылается (прямо или косвенно). Очищенные объекты не обязательно находятся в согласованном состоянии; финализированный объект должен корректно работать с очищенными объектами, на которые он ссылается.Примечание
Не гарантируется, что объект будет автоматически финализирован до вызова его деструктора (
tp_dealloc). Рекомендуется вызыватьPyObject_CallFinalizerFromDealloc()в началеtp_dealloc, чтобы гарантировать финализацию объекта до его уничтожения.Примечание
Функция
tp_finalizeможет быть вызвана из любого потока, однако при этом будет удерживаться GIL.Примечание
Функция
tp_finalizeможет быть вызвана во время завершения работы после удаления некоторых глобальных переменных. Подробности см. в документации метода__del__().При финализации объекта Python действует по следующему алгоритму:
- Python может пометить объект как финализированный. В настоящее время Python всегда помечает объекты, тип которых поддерживает сборку мусора (то есть в
tp_flagsустановлен флагPy_TPFLAGS_HAVE_GC), и никогда не помечает объекты других типов; в будущей версии это может измениться. - Если объект не помечен как финализированный, а его функция финализации
tp_finalizeне равнаNULL, вызывается эта функция. - Если функция финализации была вызвана и объект стал доступен из программы (то есть на объект имеется ссылка, и он не является членом циклического изолята), считается, что финализатор воскресил объект. Не определено, может ли финализатор также воскресить объект, добавив на него новую ссылку, которая не сделает его доступным из программы, то есть объект по-прежнему останется членом циклического изолята.
- Если финализатор воскресил объект, его предстоящее уничтожение отменяется, а отметка финализированного объекта может быть снята, если она была установлена. В настоящее время Python никогда не снимает эту отметку; в будущей версии это может измениться.
Автоматическая финализация — это любая финализация, выполняемая Python, кроме вызовов
PyObject_CallFinalizer()илиPyObject_CallFinalizerFromDealloc(). Не гарантируется, когда, будет ли и как часто объект финализирован автоматически, за исключением следующих случаев:- Python не будет автоматически финализировать объект, если он доступен из программы, то есть на него имеется ссылка, и он не является членом циклического изолята.
- Python не будет автоматически финализировать объект, если его финализация не пометит объект как финализированный. В настоящее время это относится к объектам, тип которых не поддерживает сборку мусора, то есть флаг
Py_TPFLAGS_HAVE_GCне установлен. Такие объекты всё же можно финализировать вручную, вызвавPyObject_CallFinalizer()илиPyObject_CallFinalizerFromDealloc(). - Python не будет автоматически финализировать одновременно два объекта, являющихся членами одного циклического изолята.
- Python не будет автоматически финализировать объект после его автоматической очистки (см.
tp_clear). - Если объект является членом циклического изолята, Python не будет автоматически финализировать его после автоматической очистки (см.
tp_clear) любого другого члена. - Python автоматически финализирует каждый объект, являющийся членом циклического изолята, прежде чем автоматически очистит (см.
tp_clear) любой из них. - Если Python собирается автоматически очистить объект (
tp_clear), он сначала автоматически финализирует этот объект.
В настоящее время Python автоматически финализирует только объекты, являющиеся членами циклического изолята, однако в будущих версиях объекты могут финализироваться регулярно, до их уничтожения.
Чтобы вручную финализировать объект, не вызывайте эту функцию напрямую; вместо неё вызовите
PyObject_CallFinalizer()илиPyObject_CallFinalizerFromDealloc().tp_finalizeдолжна оставлять текущее состояние исключения неизменным. Рекомендуемый способ написания нетривиального финализатора — сохранить исключение в начале вызовомPyErr_GetRaisedException(), а в конце восстановить его вызовомPyErr_SetRaisedException(). Если в ходе финализации возникает исключение, зарегистрируйте его и очистите состояние исключения с помощьюPyErr_WriteUnraisable()илиPyErr_FormatUnraisable(). Например:static void foo_finalize(PyObject *self) { // Save the current exception, if any. PyObject *exc = PyErr_GetRaisedException(); // ... if (do_something_that_might_raise() != success_indicator) { PyErr_WriteUnraisable(self); goto done; } done: // Restore the saved exception. This silently discards any exception // raised above, so be sure to call PyErr_WriteUnraisable first if // necessary. PyErr_SetRaisedException(exc); }Наследование:
Это поле наследуется подклассами.
Добавлено в версии 3.4.
Изменено в версии 3.8: До версии 3.8 для использования этого поля требовалось устанавливать бит флага
Py_TPFLAGS_HAVE_FINALIZE. Теперь это не требуется.См. также
- PEP 442: «Безопасная финализация объектов»
- Жизненный цикл объекта: подробности о связи этого слота с другими слотами.
PyObject_CallFinalizer()PyObject_CallFinalizerFromDealloc()
- Python может пометить объект как финализированный. В настоящее время Python всегда помечает объекты, тип которых поддерживает сборку мусора (то есть в
-
vectorcallfunc PyTypeObject.tp_vectorcall -
Соответствующий идентификатор слота
Py_tp_vectorcallвходит в стабильный ABI начиная с версии 3.14.Функция vectorcall, используемая для вызовов этого объекта типа (а не его экземпляров). Иными словами,
tp_vectorcallможно использовать для оптимизацииtype.__call__, которая обычно возвращает новый экземпляр типа.Как и в случае с любой функцией vectorcall, если
tp_vectorcallравноNULL, вместо этого используется протокол tp_call (Py_TYPE(type)->tp_call).Примечание
Протокол vectorcall требует, чтобы функция vectorcall имела такое же поведение, как соответствующий
tp_call. Это означает, чтоtype->tp_vectorcallдолжен соответствовать поведениюPy_TYPE(type)->tp_call.В частности, если тип использует метакласс по умолчанию,
type->tp_vectorcallдолжен вести себя так же, как PyType_Type->tp_call, который:- вызывает
type->tp_new, - если результат является подклассом типа, вызывает
type->tp_initдля результатаtp_newи - возвращает результат
tp_new.
Обычно
tp_vectorcallпереопределяют, чтобы оптимизировать этот процесс для конкретныхtp_newиtp_init. При этом для типов, которые могут иметь пользовательские подклассы, учитывайте, что оба метода можно переопределить (с помощью__new__()и__init__()соответственно).Наследование:
Это поле никогда не наследуется.
Добавлено в версии 3.9: (поле существует с версии 3.8, но используется только начиная с версии 3.9)
- вызывает
-
unsigned char PyTypeObject.tp_watched -
Внутреннее поле. Не используйте.
Добавлено в версии 3.12.
Статические типы
Традиционно типы, определённые в коде на C, являются статическими: это означает, что статическая структура PyTypeObject определяется непосредственно в коде и инициализируется с помощью PyType_Ready().
В результате такие типы имеют ограничения по сравнению с типами, определёнными в Python:
- Статические типы могут иметь только один базовый тип, то есть не поддерживают множественное наследование.
- Объекты статических типов (но не обязательно их экземпляры) неизменяемы. Из Python нельзя добавлять или изменять атрибуты объекта типа.
- Объекты статических типов совместно используются субинтерпретаторами, поэтому они не должны содержать состояние, специфичное для субинтерпретатора.
Кроме того, поскольку PyTypeObject входит в ограниченный API только как непрозрачная структура, любые модули расширения, использующие статические типы, необходимо компилировать для конкретной минорной версии Python.
Динамические типы
Альтернативой статическим типам являются типы, выделяемые в куче, или, короче, динамические типы, которые близки по устройству к классам, создаваемым оператором class в Python. У динамических типов установлен флаг Py_TPFLAGS_HEAPTYPE.
Для этого заполняют структуру PyType_Spec и вызывают PyType_FromSpec(), PyType_FromSpecWithBases(), PyType_FromModuleAndSpec() или PyType_FromMetaclass().
Структуры числовых объектов
-
type PyNumberMethods -
Эта структура содержит указатели на функции, которые объект использует для реализации числового протокола. Каждая функция используется одноимённой функцией, описанной в разделе Числовой протокол.
Определение структуры:
typedef struct { binaryfunc nb_add; binaryfunc nb_subtract; binaryfunc nb_multiply; binaryfunc nb_remainder; binaryfunc nb_divmod; ternaryfunc nb_power; unaryfunc nb_negative; unaryfunc nb_positive; unaryfunc nb_absolute; inquiry nb_bool; unaryfunc nb_invert; binaryfunc nb_lshift; binaryfunc nb_rshift; binaryfunc nb_and; binaryfunc nb_xor; binaryfunc nb_or; unaryfunc nb_int; void *nb_reserved; unaryfunc nb_float; binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; binaryfunc nb_inplace_rshift; binaryfunc nb_inplace_and; binaryfunc nb_inplace_xor; binaryfunc nb_inplace_or; binaryfunc nb_floor_divide; binaryfunc nb_true_divide; binaryfunc nb_inplace_floor_divide; binaryfunc nb_inplace_true_divide; unaryfunc nb_index; binaryfunc nb_matrix_multiply; binaryfunc nb_inplace_matrix_multiply; } PyNumberMethods;Примечание
Бинарные и тернарные функции должны проверять типы всех своих операндов и выполнять необходимые преобразования (по крайней мере один из операндов является экземпляром определённого типа). Если операция не определена для заданных операндов, бинарные и тернарные функции должны возвращать
Py_NotImplemented; если произошла другая ошибка, они должны возвращатьNULLи устанавливать исключение.Примечание
Поле
nb_reservedвсегда должно иметь значениеNULL. Ранее оно называлосьnb_long; это имя было изменено в Python 3.0.1.
-
binaryfunc PyNumberMethods.nb_add -
Соответствующий идентификатор слота
Py_nb_addвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_subtract -
Соответствующий идентификатор слота
Py_nb_subtractвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_multiply -
Соответствующий идентификатор слота
Py_nb_multiplyвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_remainder -
Соответствующий идентификатор слота
Py_nb_remainderвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_divmod -
Соответствующий идентификатор слота
Py_nb_divmodвходит в стабильный ABI.
-
ternaryfunc PyNumberMethods.nb_power -
Соответствующий идентификатор слота
Py_nb_powerвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_negative -
Соответствующий идентификатор слота
Py_nb_negativeвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_positive -
Соответствующий идентификатор слота
Py_nb_positiveвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_absolute -
Соответствующий идентификатор слота
Py_nb_absoluteвходит в стабильный ABI.
-
inquiry PyNumberMethods.nb_bool -
Соответствующий идентификатор слота
Py_nb_boolвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_invert -
Соответствующий идентификатор слота
Py_nb_invertвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_lshift -
Соответствующий идентификатор слота
Py_nb_lshiftвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_rshift -
Соответствующий идентификатор слота
Py_nb_rshiftвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_and -
Соответствующий идентификатор слота
Py_nb_andвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_xor -
Соответствующий идентификатор слота
Py_nb_xorвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_or -
Соответствующий идентификатор слота
Py_nb_orвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_int -
Соответствующий идентификатор слота
Py_nb_intвходит в стабильный ABI.
-
void *PyNumberMethods.nb_reserved
-
unaryfunc PyNumberMethods.nb_float -
Соответствующий идентификатор слота
Py_nb_floatвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_add -
Соответствующий идентификатор слота
Py_nb_inplace_addвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_subtract -
Соответствующий идентификатор слота
Py_nb_inplace_subtractвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_multiply -
Соответствующий идентификатор слота
Py_nb_inplace_multiplyвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_remainder -
Соответствующий идентификатор слота
Py_nb_inplace_remainderвходит в стабильный ABI.
-
ternaryfunc PyNumberMethods.nb_inplace_power -
Соответствующий идентификатор слота
Py_nb_inplace_powerвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_lshift -
Соответствующий идентификатор слота
Py_nb_inplace_lshiftвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_rshift -
Соответствующий идентификатор слота
Py_nb_inplace_rshiftвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_and -
Соответствующий идентификатор слота
Py_nb_inplace_andвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_xor -
Соответствующий идентификатор слота
Py_nb_inplace_xorвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_or -
Соответствующий идентификатор слота
Py_nb_inplace_orвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_floor_divide -
Соответствующий идентификатор слота
Py_nb_floor_divideвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_true_divide -
Соответствующий идентификатор слота
Py_nb_true_divideвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_floor_divide -
Соответствующий идентификатор слота
Py_nb_inplace_floor_divideвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_inplace_true_divide -
Соответствующий идентификатор слота
Py_nb_inplace_true_divideвходит в стабильный ABI.
-
unaryfunc PyNumberMethods.nb_index -
Соответствующий идентификатор слота
Py_nb_indexвходит в стабильный ABI.
-
binaryfunc PyNumberMethods.nb_matrix_multiply -
Соответствующий идентификатор слота
Py_nb_matrix_multiplyвходит в стабильный ABI начиная с версии 3.5.
-
binaryfunc PyNumberMethods.nb_inplace_matrix_multiply -
Соответствующий идентификатор слота
Py_nb_inplace_matrix_multiplyвходит в стабильный ABI начиная с версии 3.5.
Структуры объектов отображения
-
type PyMappingMethods -
Эта структура содержит указатели на функции, с помощью которых объект реализует протокол отображения. Она имеет три поля:
-
lenfunc PyMappingMethods.mp_length -
Соответствующий идентификатор слота
Py_mp_lengthвходит в стабильный ABI.Эта функция используется функциями
PyMapping_Size()иPyObject_Size()и имеет ту же сигнатуру. Для объектов с неопределённой длиной этому слоту можно присвоитьNULL.
-
binaryfunc PyMappingMethods.mp_subscript -
Соответствующий идентификатор слота
Py_mp_subscriptвходит в стабильный ABI.Эта функция используется функциями
PyObject_GetItem()иPySequence_GetSlice()и имеет ту же сигнатуру, что иPyObject_GetItem(). Этот слот должен быть заполнен, чтобы функцияPyMapping_Check()возвращала1; в противном случае ему можно присвоитьNULL.
-
objobjargproc PyMappingMethods.mp_ass_subscript -
Соответствующий идентификатор слота
Py_mp_ass_subscriptвходит в стабильный ABI.Эта функция используется функциями
PyObject_SetItem(),PyObject_DelItem(),PySequence_SetSlice()иPySequence_DelSlice(). Она имеет ту же сигнатуру, что иPyObject_SetItem(), но v также можно установить вNULL, чтобы удалить элемент. Если этому слоту присвоеноNULL, объект не поддерживает присваивание и удаление элементов.
Структуры объектов последовательностей
-
type PySequenceMethods -
Эта структура содержит указатели на функции, с помощью которых объект реализует протокол последовательности.
-
lenfunc PySequenceMethods.sq_length -
Соответствующий идентификатор слота
Py_sq_lengthвходит в стабильный ABI.Эта функция используется функциями
PySequence_Size()иPyObject_Size()и имеет ту же сигнатуру. Она также используется для обработки отрицательных индексов слотамиsq_itemиsq_ass_item.
-
binaryfunc PySequenceMethods.sq_concat -
Соответствующий идентификатор слота
Py_sq_concatвходит в стабильный ABI.Эта функция используется функцией
PySequence_Concat()и имеет ту же сигнатуру. Она также используется оператором+после попытки выполнить числовое сложение с помощью слотаnb_add.
-
ssizeargfunc PySequenceMethods.sq_repeat -
Соответствующий идентификатор слота
Py_sq_repeatвходит в стабильный ABI.Эта функция используется функцией
PySequence_Repeat()и имеет ту же сигнатуру. Она также используется оператором*после попытки выполнить числовое умножение с помощью слотаnb_multiply.
-
ssizeargfunc PySequenceMethods.sq_item -
Соответствующий идентификатор слота
Py_sq_itemвходит в стабильный ABI.Эта функция используется функцией
PySequence_GetItem()и имеет ту же сигнатуру. Она также используется функциейPyObject_GetItem()после попытки выполнить индексирование с помощью слотаmp_subscript. Этот слот должен быть заполнен, чтобы функцияPySequence_Check()возвращала1; в противном случае ему можно присвоитьNULL.Отрицательные индексы обрабатываются следующим образом: если слот
sq_lengthзаполнен, он вызывается, а длина последовательности используется для вычисления положительного индекса, который передаётся вsq_item. Еслиsq_lengthимеет значениеNULL, индекс передаётся функции без изменений.
-
ssizeobjargproc PySequenceMethods.sq_ass_item -
Соответствующий идентификатор слота
Py_sq_ass_itemвходит в стабильный ABI.Эта функция используется функцией
PySequence_SetItem()и имеет ту же сигнатуру. Она также используется функциямиPyObject_SetItem()иPyObject_DelItem()после попытки выполнить присваивание и удаление элемента с помощью слотаmp_ass_subscript. Если объект не поддерживает присваивание и удаление элементов, этому слоту можно присвоитьNULL.
-
objobjproc PySequenceMethods.sq_contains -
Соответствующий идентификатор слота
Py_sq_containsвходит в стабильный ABI.Эта функция может использоваться функцией
PySequence_Contains()и имеет ту же сигнатуру. Этому слоту можно присвоитьNULL; в этом случаеPySequence_Contains()просто перебирает последовательность, пока не найдёт совпадение.
-
binaryfunc PySequenceMethods.sq_inplace_concat -
Соответствующий идентификатор слота
Py_sq_inplace_concatвходит в стабильный ABI.Эта функция используется функцией
PySequence_InPlaceConcat()и имеет ту же сигнатуру. Она должна изменять свой первый операнд и возвращать его. Этому слоту можно присвоитьNULL; в этом случаеPySequence_InPlaceConcat()использует в качестве запасного вариантаPySequence_Concat(). Он также используется при расширенном присваивании+=после попытки выполнить числовое сложение на месте с помощью слотаnb_inplace_add.
-
ssizeargfunc PySequenceMethods.sq_inplace_repeat -
Соответствующий идентификатор слота
Py_sq_inplace_repeatвходит в стабильный ABI.Эта функция используется функцией
PySequence_InPlaceRepeat()и имеет ту же сигнатуру. Она должна изменять свой первый операнд и возвращать его. Этому слоту можно присвоитьNULL; в этом случаеPySequence_InPlaceRepeat()использует в качестве запасного вариантаPySequence_Repeat(). Он также используется при расширенном присваивании*=после попытки выполнить числовое умножение на месте с помощью слотаnb_inplace_multiply.
Структуры объектов буфера
-
type PyBufferProcs -
Эта структура содержит указатели на функции, необходимые для протокола буфера. Протокол определяет, как объект-экспортер может предоставлять свои внутренние данные объектам-потребителям.
-
getbufferproc PyBufferProcs.bf_getbuffer -
Соответствующий идентификатор слота
Py_bf_getbufferвходит в стабильный ABI начиная с версии 3.11.Сигнатура этой функции:
int (PyObject *exporter, Py_buffer *view, int flags);
Обрабатывает запрос к экспортеру заполнить view в соответствии с flags. За исключением пункта (3), реализация этой функции ДОЛЖНА выполнить следующие действия:
- Проверить, можно ли выполнить запрос. Если нет, вызвать исключение
BufferError, установитьview->objвNULLи вернуть-1. - Заполнить запрошенные поля.
- Увеличить внутренний счетчик количества экспортов.
- Установить
view->objв exporter и увеличитьview->obj. - Вернуть
0.
Потокобезопасность:
В сборке без GIL реализации должны обеспечивать следующее:
- Увеличение счетчика экспортов на шаге (3) выполняется атомарно.
- Базовые данные буфера остаются действительными и находятся по неизменному адресу в памяти в течение всего времени существования всех экспортов.
- Для объектов, поддерживающих изменение размера или перераспределение памяти (например,
bytearray), перед такими операциями счетчик экспортов проверяется атомарно, а если существуют экспорты, вызывается исключениеBufferError. - Функцию можно безопасно вызывать одновременно из нескольких потоков.
Сведения о гарантиях потокобезопасности
memoryviewна уровне Python см. в разделе Потокобезопасность объектов memoryview.Если exporter входит в цепочку или дерево поставщиков буфера, можно использовать две основные схемы:
- Повторный экспорт: каждый элемент дерева выступает в роли экспортирующего объекта и устанавливает
view->objв новое сильное ссылочное значение на себя. - Перенаправление: запрос буфера перенаправляется корневому объекту дерева. В этом случае
view->objбудет новым сильным ссылочным значением на корневой объект.
Отдельные поля view описаны в разделе Структура буфера, а правила поведения экспортера при определенных запросах приведены в разделе Типы запросов буфера.
Вся память, на которую указывают поля структуры
Py_buffer, принадлежит экспортеру и должна оставаться действительной, пока существуют потребители. Поляformat,shape,strides,suboffsetsиinternalдоступны потребителю только для чтения.PyBuffer_FillInfo()позволяет легко предоставить простой буфер байтов, корректно обрабатывая при этом все типы запросов.PyObject_GetBuffer()— интерфейс потребителя, оборачивающий эту функцию. - Проверить, можно ли выполнить запрос. Если нет, вызвать исключение
-
releasebufferproc PyBufferProcs.bf_releasebuffer -
Соответствующий идентификатор слота
Py_bf_releasebufferвходит в стабильный ABI начиная с версии 3.11.Сигнатура этой функции:
void (PyObject *exporter, Py_buffer *view);
Обрабатывает запрос на освобождение ресурсов буфера. Если освобождать ресурсы не требуется, значение
PyBufferProcs.bf_releasebufferможет бытьNULL. В противном случае стандартная реализация этой функции может выполнить следующие действия:- Уменьшить внутренний счетчик количества экспортов.
- Если значение счетчика равно
0, освободить всю память, связанную с view.
Потокобезопасность:
- Уменьшение счетчика экспортов на шаге (1) должно выполняться атомарно.
- Очистка ресурсов при достижении счетчиком нуля должна выполняться атомарно, поскольку окончательное освобождение может происходить одновременно с освобождением в других потоках, а освобождение памяти должно выполняться только один раз.
Экспортер ДОЛЖЕН использовать поле
internalдля отслеживания ресурсов, связанных с буфером. Это поле гарантированно остается неизменным, хотя потребитель МОЖЕТ передать копию исходного буфера в качестве аргумента view.Эта функция НЕ ДОЛЖНА уменьшать
view->obj, поскольку это автоматически выполняется вPyBuffer_Release()(эта схема полезна для разрыва циклов ссылок).PyBuffer_Release()— интерфейс потребителя, оборачивающий эту функцию.
Структуры асинхронных объектов
Добавлено в версии 3.5.
-
type PyAsyncMethods -
Эта структура содержит указатели на функции, необходимые для реализации объектов ожидаемого объекта и асинхронного итератора.
Определение структуры:
typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; sendfunc am_send; } PyAsyncMethods;
-
unaryfunc PyAsyncMethods.am_await -
Соответствующий идентификатор слота
Py_am_awaitвходит в стабильный ABI начиная с версии 3.5.Сигнатура этой функции:
PyObject *am_await(PyObject *self);
Возвращаемый объект должен быть итератором, то есть для него
PyIter_Check()должен возвращать1.Для объекта, который не является ожидаемым объектом, этому слоту можно присвоить значение
NULL.
-
unaryfunc PyAsyncMethods.am_aiter -
Соответствующий идентификатор слота
Py_am_aiterвходит в стабильный ABI начиная с версии 3.5.Сигнатура этой функции:
PyObject *am_aiter(PyObject *self);
Должна возвращать объект асинхронного итератора. Подробности см. в
__anext__().Для объекта, который не реализует протокол асинхронной итерации, этому слоту можно присвоить значение
NULL.
-
unaryfunc PyAsyncMethods.am_anext -
Соответствующий идентификатор слота
Py_am_anextвходит в стабильный ABI начиная с версии 3.5.Сигнатура этой функции:
PyObject *am_anext(PyObject *self);
Должна возвращать объект ожидаемого объекта. Подробности см. в
__anext__(). Этому слоту можно присвоить значениеNULL.
-
sendfunc PyAsyncMethods.am_send -
Соответствующий идентификатор слота
Py_am_sendвходит в стабильный ABI начиная с версии 3.10.Сигнатура этой функции:
PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);
Подробности см. в
PyIter_Send(). Этому слоту можно присвоить значениеNULL.Добавлено в версии 3.10.
Определения типов слотов
-
typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems) -
Часть стабильного ABI.
Назначение этой функции — отделить выделение памяти от инициализации памяти. Она должна возвращать указатель на блок памяти достаточной длины для экземпляра, правильно выровненный и инициализированный нулями, при этом
ob_refcntдолжен быть установлен в1, аob_type— в аргумент типа. Еслиtp_itemsizeтипа не равен нулю, полеob_sizeобъекта следует инициализировать значением nitems, а длина выделенного блока памяти должна составлятьtp_basicsize + nitems*tp_itemsize, округлённое вверх до ближайшего кратногоsizeof(void*); в противном случае nitems не используется, а длина блока должна равнятьсяtp_basicsize.Эта функция не должна выполнять никакую другую инициализацию экземпляра, даже выделять дополнительную память; это должна делать
tp_new.
-
typedef void (*destructor)(PyObject*) - Часть стабильного ABI.
-
typedef void (*freefunc)(void*) -
См.
tp_free.
-
typedef PyObject *(*newfunc)(PyTypeObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_new.
-
typedef int (*initproc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_init.
-
typedef PyObject *(*reprfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_repr.
-
typedef PyObject *(*getattrfunc)(PyObject *self, char *attr) -
Часть стабильного ABI.
Возвращает значение именованного атрибута объекта.
-
typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value) -
Часть стабильного ABI.
Устанавливает значение именованного атрибута объекта. Для удаления атрибута аргумент value устанавливается в
NULL.
-
typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr) -
Часть стабильного ABI.
Возвращает значение именованного атрибута объекта.
См.
tp_getattro.
-
typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value) -
Часть стабильного ABI.
Устанавливает значение именованного атрибута объекта. Для удаления атрибута аргумент value устанавливается в
NULL.См.
tp_setattro.
-
typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_descr_get.
-
typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_descr_set.
-
typedef Py_hash_t (*hashfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_hash.
-
typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int) -
Часть стабильного ABI.
См.
tp_richcompare.
-
typedef PyObject *(*getiterfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_iter.
-
typedef PyObject *(*iternextfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_iternext.
-
typedef Py_ssize_t (*lenfunc)(PyObject*) - Часть стабильного ABI.
-
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int) - Часть стабильного ABI начиная с версии 3.12.
-
typedef void (*releasebufferproc)(PyObject*, Py_buffer*) - Часть стабильного ABI начиная с версии 3.12.
-
typedef PyObject *(*unaryfunc)(PyObject*) - Часть стабильного ABI.
-
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**) -
См.
am_send.
-
typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t) - Часть стабильного ABI.
-
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*) - Часть стабильного ABI.
-
typedef int (*objobjproc)(PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*) - Часть стабильного ABI.
Примеры
Ниже приведены простые примеры определений типов 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 = PyDoc_STR("My objects"),
.tp_new = myobj_new,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
};
В старом коде (особенно в исходном коде CPython) также может встречаться более многословный инициализатор:
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mymod.MyObject", /* tp_name */
sizeof(MyObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)myobj_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)myobj_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
PyDoc_STR("My objects"), /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
myobj_new, /* tp_new */
};
Тип, поддерживающий слабые ссылки, словари экземпляров и хеширование:
typedef struct {
PyObject_HEAD
const char *data;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = PyDoc_STR("My objects"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
Py_TPFLAGS_MANAGED_WEAKREF,
.tp_new = myobj_new,
.tp_traverse = (traverseproc)myobj_traverse,
.tp_clear = (inquiry)myobj_clear,
.tp_alloc = PyType_GenericNew,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
.tp_hash = (hashfunc)myobj_hash,
.tp_richcompare = PyBaseObject_Type.tp_richcompare,
};
Подкласс str, который нельзя дополнительно наследовать и нельзя вызывать для создания экземпляров (например, он использует отдельную фабричную функцию), с флагом Py_TPFLAGS_DISALLOW_INSTANTIATION:
typedef struct {
PyUnicodeObject raw;
char *extra;
} MyStr;
static PyTypeObject MyStr_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyStr",
.tp_basicsize = sizeof(MyStr),
.tp_base = NULL, // set to &PyUnicode_Type in module init
.tp_doc = PyDoc_STR("my custom str"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.tp_repr = (reprfunc)myobj_repr,
};
Самый простой статический тип с экземплярами фиксированной длины:
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 *),
};
© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/c-api/typeobj.html