Объекты типов
Возможно, одной из самых важных структур системы объектов Python является структура, определяющая новый тип: структура PyTypeObject. Объекты типов можно обрабатывать с помощью любых из функций PyObject_*() или PyType_*(), но они не предлагают много интересного для большинства приложений Python. Эти объекты фундаментальны для поведения объектов, поэтому они очень важны для самого интерпретатора и для любого модуля расширения, реализующего новые типы.
Объекты типов довольно велики по сравнению с большинством стандартных типов. Причина в том, что каждый объект типа хранит большое количество значений, в основном указатели на функции C, каждая из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно изучаются в этом разделе. Поля будут описаны в порядке их появления в структуре.
В дополнение к следующей краткой справке, раздел Примеры предоставляет наглядное представление о значении и использовании PyTypeObject.
Быстрый справочник
“tp slots”
Раздел объекта типа PyTypeObject 1 | специальные методы/атрибуты | Информация 2 | ||||
|---|---|---|---|---|---|---|
О | Т | Д | И | |||
<R> | const char * | __name__ | X | X | ||
Py_ssize_t | X | X | X | |||
Py_ssize_t | X | X | ||||
X | X | X | ||||
Py_ssize_t | ? | |||||
__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 | ||||
Py_ssize_t | X | ? | ||||
__iter__ | X | |||||
__next__ | X | |||||
| X | X | ||||
| X | |||||
| X | X | ||||
__base__ | X | |||||
| __dict__ | ? | ||||
__get__ | X | |||||
__set__, __delete__ | X | |||||
Py_ssize_t | X | ? | ||||
__init__ | X | X | X | |||
X | ? | ? | ||||
__new__ | X | X | ? | ? | ||
X | X | ? | ? | |||
X | X | |||||
< |
| __bases__ | ~ | |||
< |
| __mro__ | ~ | |||
[ |
| |||||
| __subclasses__ | |||||
| ||||||
( | ||||||
unsigned int | ||||||
__del__ | X | |||||
Если COUNT_ALLOCS определено, то следующие (только для внутренней работы) поля также существуют:
-
1 -
Имя слота в скобках указывает, что он (фактически) устарел. Имена в угловых скобках следует рассматривать как только для чтения. Имена в квадратных скобках предназначены только для внутреннего использования. «<R>» (в качестве префикса) означает, что поле является обязательным (должно быть отличным от
NULL). -
2 -
Столбцы:
“O”: устанавливается на
PyBaseObject_Type“T”: устанавливается на
PyType_Type“D”: значение по умолчанию (если слот установлен на
NULL)X - PyType_Ready sets this value if it is NULL ~ - PyType_Ready always sets this value (it should be NULL) ? - PyType_Ready may set this value depending on other slots Also see the inheritance column ("I").“I”: наследование
X - type slot is inherited via PyType_Ready if defined with a NULL value % - the slots of the sub-struct are inherited individually G - inherited, but only in combination with other slots; see the slot's description ? - it's complicated; see the slot's description
Обратите внимание, что некоторые слоты фактически наследуются через стандартную цепочку поиска атрибутов.
sub-слоты
Слоты | специальные методы | |
|---|---|---|
__await__ | ||
__aiter__ | ||
__anext__ | ||
__add__ __radd__ | ||
__iadd__ | ||
__sub__ __rsub__ | ||
__sub__ | ||
__mul__ __rmul__ | ||
__mul__ | ||
__mod__ __rmod__ | ||
__mod__ | ||
__divmod__ __rdivmod__ | ||
__pow__ __rpow__ | ||
__pow__ | ||
__neg__ | ||
__pos__ | ||
__abs__ | ||
__bool__ | ||
__invert__ | ||
__lshift__ __rlshift__ | ||
__lshift__ | ||
__rshift__ __rrshift__ | ||
__rshift__ | ||
__and__ __rand__ | ||
__and__ | ||
__xor__ __rxor__ | ||
__xor__ | ||
__or__ __ror__ | ||
__or__ | ||
__int__ | ||
void * | ||
__float__ | ||
__floordiv__ | ||
__floordiv__ | ||
__truediv__ | ||
__truediv__ | ||
__index__ | ||
__matmul__ __rmatmul__ | ||
__matmul__ | ||
__len__ | ||
__getitem__ | ||
__setitem__, __delitem__ | ||
__len__ | ||
__add__ | ||
__mul__ | ||
__getitem__ | ||
__setitem__ __delitem__ | ||
__contains__ | ||
__iadd__ | ||
__imul__ | ||
типы определений слотов
typedef | Типы параметров | Тип возвращаемого значения |
|---|---|---|
| ||
void * | void | |
void * | void | |
int | ||
| ||
int | ||
|
| |
| ||
int | ||
| ||
int | ||
| ||
int | ||
| Py_hash_t | |
| ||
|
| |
|
| |
| Py_ssize_t | |
int | ||
void | ||
void * | int | |
| ||
| ||
| ||
| ||
int | ||
int | ||
int |
Подробная информация см. в разделе Типы определений слотов ниже.
Определение PyTypeObject
Определение структуры PyTypeObject можно найти в Include/object.h. Для удобства ссылки, здесь приводится это определение:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag;
destructor tp_finalize;
} PyTypeObject;
Слоты PyObject
Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (созданных type_new(), обычно вызываемых из оператора класса). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, что означает, что его экземпляры (т.е. объекты типа) обязательно должны содержать поле ob_size.
-
PyObject* PyObject._ob_next -
PyObject* PyObject._ob_prev -
Эти поля присутствуют только при определении макроса
Py_TRACE_REFS. Их инициализация значениемNULLвыполняется макросомPyObject_HEAD_INIT. Для статически выделенных объектов эти поля всегда остаютсяNULL. Для динамически выделенных объектов эти два поля используются для связывания объекта в список парно-связанных списков всех активных объектов в куче. Это может быть полезно для различных целей отладки; в настоящее время единственное использование — вывести список объектов, которые все ещё активны в конце выполнения, когда переменная средыPYTHONDUMPREFSустановлена.Наследование:
Эти поля не наследуются подтипами.
-
Py_ssize_t PyObject.ob_refcnt -
Это счётчик ссылок объекта типа, инициализируемый значением
1макросомPyObject_HEAD_INIT. Обратите внимание, что для статически выделенных объектов типа, экземпляры типа (объекты, чьё полеob_typeуказывает на тип) не считаются ссылками. Но для динамически выделенных объектов типа, экземпляры считаются ссылками.Наследование:
Это поле не наследуется подтипами.
-
PyTypeObject* PyObject.ob_type -
Это тип типа, другими словами, его метатип. Он инициализируется аргументом макроса
PyObject_HEAD_INIT, и его значение обычно должно быть&PyType_Type. Однако для динамически загружаемых расширений модулей, которые должны быть совместимы с Windows (по крайней мере), компилятор жалуется на то, что это не допустимое значение инициализации. Поэтому соглашение состоит в том, чтобы передатьNULLв макросPyObject_HEAD_INITи явно инициализировать это поле в начале функции инициализации модуля, перед любыми другими действиями. Обычно это делается так:Foo_Type.ob_type = &PyType_Type;
Это должно быть сделано до создания каких-либо экземпляров типа.
PyType_Ready()проверяет, является лиob_typeравнымNULL, и если да, инициализирует его значением поляob_typeбазового класса.PyType_Ready()не изменит это поле, если оно уже не равно нулю.Наследование:
Это поле наследуется подтипами.
Слоты PyVarObject
-
Py_ssize_t PyVarObject.ob_size -
Для статически выделенных объектов типа это значение должно быть равно нулю. Для динамически выделенных объектов типа это поле имеет специальное внутреннее значение.
Наследование:
Это поле не наследуется подтипами.
Свойства объекта PyTypeObject
У каждого свойства есть раздел, описывающий наследование. Если PyType_Ready() может установить значение, когда поле установлено в NULL , тогда также будет раздел «Значение по умолчанию». (Обратите внимание, что многие поля, установленные на PyBaseObject_Type и PyType_Type фактически действуют как значения по умолчанию.)
-
const char* PyTypeObject.tp_name -
Указатель на строку с завершающим нулем, содержащую имя типа. Для типов, доступных в качестве глобальных переменных модуля, строка должна содержать полное имя модуля, за которым следует точка, за которой следует имя типа; для встроенных типов — только имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип, названный
T, определённый в модулеMв подпакетеQв пакетеP, должен иметь инициализаторtp_name"P.Q.M.T".Для динамически выделенных объектов типа это должно быть просто имя типа, а имя модуля явно сохраняется в словаре типа как значение для ключа
'__module__'.Для статически выделенных объектов типа поле tp_name должно содержать точку. Всё перед последней точкой делается доступным как атрибут
__module__, а всё после последней точки делается доступным как атрибут__name__.Если точка отсутствует, всё поле
tp_nameделается доступным как атрибут__name__, а атрибут__module__не определён (если не установлен явно в словаре, как описано выше). Это означает, что ваш тип будет невозможен для сериализации. Кроме того, он не будет отображаться в документации модуля, созданной с помощью pydoc.Это поле не должно быть
NULL. Это единственное обязательное поле вPyTypeObject()(кроме, возможно,tp_itemsize).Наследование:
Это поле не наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_basicsize -
Py_ssize_t PyTypeObject.tp_itemsize -
Эти поля позволяют вычислять размер в байтах экземпляров типа.
Существуют два вида типов: типы с экземплярами фиксированной длины имеют нулевое поле
tp_itemsize, типы с экземплярами переменной длины имеют ненулевое полеtp_itemsize. Для типа с экземплярами фиксированной длины все экземпляры имеют одинаковый размер, указанный вtp_basicsize.Для типа с экземплярами переменной длины экземпляры должны иметь поле
ob_size, и размер экземпляра равенtp_basicsizeплюс N разtp_itemsize, где N — «длина» объекта. Значение N обычно хранится в поле экземпляраob_size. Есть исключения: например, целые числа используют отрицательноеob_sizeдля обозначения отрицательного числа, и N равноabs(ob_size)там. Кроме того, наличие поляob_sizeв макете экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура типа списка имеет экземпляры фиксированной длины, но эти экземпляры имеют осмысленное полеob_size).Базовый размер включает поля в экземпляре, объявленные макросом
PyObject_HEADилиPyObject_VAR_HEAD(которое используется для объявления структуры экземпляра), и это, в свою очередь, включает поля_ob_prevи_ob_next, если они присутствуют. Это означает, что единственный правильный способ получить инициализатор дляtp_basicsize— использовать операторsizeofна структуре, используемой для объявления макета экземпляра. Базовый размер не включает размер заголовка GC.Примечание об выравнивании: если для переменных элементов требуется определённое выравнивание, это должно быть учтено значением
tp_basicsize. Пример: предположим, что тип реализует массивdouble.tp_itemsizeравноsizeof(double). От программиста требуется, чтобыtp_basicsizeбыло кратноsizeof(double)(предполагая, что это требование выравнивания дляdouble).Для любого типа с экземплярами переменной длины это поле не должно быть
NULL.Наследование:
Эти поля наследуются подтипами отдельно. Если базовый тип имеет ненулевое
tp_itemsize, обычно небезопасно устанавливатьtp_itemsizeв другое ненулевое значение в подтипе (хотя это зависит от реализации базового типа).
-
destructor PyTypeObject.tp_dealloc -
Указатель на функцию-деструктор экземпляра. Эта функция должна быть определена, если тип не гарантирует, что его экземпляры никогда не будут удалены (как в случае с одиночками
NoneиEllipsis). Подпись функции:void tp_dealloc(PyObject *self);
Функция-деструктор вызывается макросами
Py_DECREF()иPy_XDECREF(), когда новый счётчик ссылок равен нулю. На этом этапе экземпляр всё ещё существует, но ссылок на него нет. Функция-деструктор должна освободить все ссылки, которыми владеет экземпляр, освободить все буферы памяти, которыми владеет экземпляр (используя функцию освобождения, соответствующую функции выделения, используемой для выделения буфера), и вызвать функциюtp_freeтипа. Если тип не подтипируемый (в нём не установлен флагPy_TPFLAGS_BASETYPE), разрешается вызывать деаллокатор объекта напрямую вместоtp_free. Деаллокатор объекта должен быть тем, который использовался для выделения экземпляра; это обычноPyObject_Del(), если экземпляр был выделен с помощьюPyObject_New()илиPyObject_VarNew(), илиPyObject_GC_Del(), если экземпляр был выделен с помощьюPyObject_GC_New()илиPyObject_GC_NewVar().Наконец, если тип выделяется в куче (
Py_TPFLAGS_HEAPTYPE), деаллокатор должен уменьшить счётчик ссылок на объект типа после вызова деаллокатора типа. Для того чтобы избежать висячих указателей, рекомендуется сделать это следующим образом:static void foo_dealloc(foo_object *self) { PyTypeObject *tp = Py_TYPE(self); // free references and buffers here tp->tp_free(self); Py_DECREF(tp); }Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset -
Дополнительный смещение к функции на экземпляре, которая реализует вызов объекта с помощью протокола vectorcall, более эффективной альтернативой простому
tp_call.Это поле используется только в том случае, если установлен флаг
_Py_TPFLAGS_HAVE_VECTORCALL. Если это так, это должно быть положительное целое число, содержащее смещение в экземпляре указателяvectorcallfunc. Подпись такая же, как и для_PyObject_Vectorcall():PyObject *vectorcallfunc(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Указатель vectorcallfunc может быть нулевым, в этом случае экземпляр ведет себя так, как будто
_Py_TPFLAGS_HAVE_VECTORCALLне был установлен: вызов экземпляра возвращается кtp_call.Любой класс, который устанавливает
_Py_TPFLAGS_HAVE_VECTORCALL, также должен установитьtp_callи убедиться, что его поведение согласуется с функцией vectorcallfunc. Это можно сделать, установив tp_call вPyVectorcall_Call:-
PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict) -
Вызов vectorcallfunc для callable с позиционными и именованными аргументами, заданными в кортеже и словаре соответственно.
Эта функция предназначена для использования в слоте
tp_call. Она не возвращается кtp_callи в настоящее время не проверяет флаг_Py_TPFLAGS_HAVE_VECTORCALL. Для вызова объекта используйте одну из функцийPyObject_Callвместо этого.
Примечание
Не рекомендуется реализовывать протокол vectorcall для типов кучи типов кучи. Когда пользователь устанавливает
__call__в коде Python, обновляется толькоtp_call, что, возможно, сделает его несогласованным с функцией vectorcall.Примечание
Семантика слота
tp_vectorcall_offsetявляется предварительной и ожидается, что она будет окончательно утверждена в Python 3.9. Если вы используете vectorcall, запланируйте обновление своего кода для Python 3.9.Изменено в версии 3.8: Этот слот использовался для форматирования вывода в Python 2.x. В Python 3.0 до 3.7 он был зарезервирован и назван
tp_print.Наследование:
Это поле наследуется подтипами вместе с
tp_call: подтип наследуетtp_vectorcall_offsetот своего базового типа, когдаtp_callподтипа равенNULL.Обратите внимание, что типы кучи типы кучи (включая подклассы, определенные в Python) не наследуют флаг
_Py_TPFLAGS_HAVE_VECTORCALL. -
-
getattrfunc PyTypeObject.tp_getattr -
Необязательный указатель на функцию получения атрибута-строки.
Это поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_getattro, но принимает строку C вместо объекта Python для имени атрибута.Наследование:
Группа:
tp_getattr,tp_getattroЭто поле наследуется подтипами вместе с
tp_getattro: подтип наследует какtp_getattr, так иtp_getattroот своего базового типа, когдаtp_getattrиtp_getattroподтипа равныNULL.
-
setattrfunc PyTypeObject.tp_setattr -
Необязательный указатель на функцию для установки и удаления атрибутов.
Это поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_setattro, но принимает строку C вместо объекта Python для имени атрибута.Наследование:
Группа:
tp_setattr,tp_setattroЭто поле наследуется подтипами вместе с
tp_setattro: подтип наследует какtp_setattr, так иtp_setattroот своего базового типа, когдаtp_setattrиtp_setattroподтипа равныNULL.
-
PyAsyncMethods* PyTypeObject.tp_as_async -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протоколы awaitable и асинхронный итератор на уровне C. Подробности см. в разделе Структуры асинхронных объектов.
Новое в версии 3.5: Ранее известен как
tp_compareиtp_reserved.Наследование:
Поле
tp_as_asyncне наследуется, но содержащиеся поля наследуются индивидуально.
-
reprfunc PyTypeObject.tp_repr -
Необязательный указатель на функцию, реализующую встроенную функцию
repr().Подпись такая же, как и для
PyObject_Repr():PyObject *tp_repr(PyObject *self);
Функция должна возвращать строку или объект Unicode. В идеале эта функция должна возвращать строку, которая, когда передается в
eval(), в подходящей среде возвращает объект с тем же значением. Если это нецелесообразно, она должна возвращать строку, начинающуюся с'<'и заканчивающуюся'>', из которой можно вывести тип и значение объекта.Наследование:
Это поле наследуется подтипами.
По умолчанию:
Если это поле не установлено, возвращается строка вида
<%s object at %p>, где%sзаменяется именем типа, а%p— адресом памяти объекта.
-
PyNumberMethods* PyTypeObject.tp_as_number -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют числовой протокол. Эти поля описаны в Структура числовых объектов.
Наследование:
Поле
tp_as_numberне наследуется, но содержащиеся поля наследуются индивидуально.
-
PySequenceMethods* PyTypeObject.tp_as_sequence -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протокол последовательности. Эти поля описаны в Структуры объектов последовательностей.
Наследование:
Поле
tp_as_sequenceне наследуется, но содержащиеся поля наследуются индивидуально.
-
PyMappingMethods* PyTypeObject.tp_as_mapping -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протокол отображения. Эти поля описаны в Структуры объектов отображения.
Наследование:
Поле
tp_as_mappingне наследуется, но содержащиеся поля наследуются индивидуально.
-
hashfunc PyTypeObject.tp_hash -
Необязательный указатель на функцию, которая реализует встроенную функцию
hash().Подпись такая же, как у
PyObject_Hash():Py_hash_t tp_hash(PyObject *);
Значение
-1не должно возвращаться как обычное возвращаемое значение; при возникновении ошибки во время вычисления значения хэша функция должна установить исключение и вернуть-1.Когда этот поле не задано (и
tp_richcompareне задано), попытка получить хэш объекта вызываетTypeError. Это эквивалентно его установке вPyObject_HashNotImplemented().Этот поле можно явно установить в
PyObject_HashNotImplemented(), чтобы заблокировать наследование метода хэширования от родительского типа. Это интерпретируется как эквивалент__hash__ = Noneна уровне Python, что приводит к тому, чтоisinstance(o, collections.Hashable)правильно возвращаетFalse. Обратите внимание, что обратное также верно — установка__hash__ = Noneдля класса на уровне Python приведет к установке слотаtp_hashвPyObject_HashNotImplemented().Наследование:
Группа:
tp_hash,tp_richcompareЭто поле наследуется подтипами вместе с
tp_richcompare: подтип наследует оба поляtp_richcompareиtp_hash, когдаtp_richcompareиtp_hashподтипа обаNULL.
-
ternaryfunc PyTypeObject.tp_call -
Необязательный указатель на функцию, которая реализует вызов объекта. Это должно быть
NULLесли объект не вызываемый. Подпись такая же, как уPyObject_Call():PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);
Наследование:
Это поле наследуется подтипами.
-
reprfunc PyTypeObject.tp_str -
Необязательный указатель на функцию, которая реализует встроенную операцию
str(). (Обратите внимание, чтоstr— это теперь тип, иstr()вызывает конструктор этого типа. Этот конструктор вызываетPyObject_Str()для выполнения фактической работы, иPyObject_Str()вызовет этот обработчик.)Подпись такая же, как у
PyObject_Str():PyObject *tp_str(PyObject *self);
Функция должна вернуть строку или объект Unicode. Это должно быть «дружественное» строковое представление объекта, которое будет использоваться, среди прочего, функцией
print().Наследование:
Это поле наследуется подтипами.
По умолчанию:
Когда это поле не задано, вызывается
PyObject_Repr(), чтобы вернуть строковое представление.
-
getattrofunc PyTypeObject.tp_getattro -
Необязательный указатель на функцию получения атрибута.
Подпись такая же, как у
PyObject_GetAttr():PyObject *tp_getattro(PyObject *self, PyObject *attr);
Обычно удобно установить это поле в
PyObject_GenericGetAttr(), который реализует стандартный способ поиска атрибутов объекта.Наследование:
Группа:
tp_getattr,tp_getattroЭто поле наследуется подтипами вместе с
tp_getattr: подтип наследует оба поляtp_getattrиtp_getattroот базового типа, когдаtp_getattrиtp_getattroподтипа обаNULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericGetAttr().
-
setattrofunc PyTypeObject.tp_setattro -
Необязательный указатель на функцию для установки и удаления атрибутов.
Подпись такая же, как у
PyObject_SetAttr():PyObject *tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
Кроме того, установка value в
NULLдля удаления атрибута должна поддерживаться. Обычно удобно установить это поле вPyObject_GenericSetAttr(), который реализует стандартный способ установки атрибутов объекта.Наследование:
Группа:
tp_setattr,tp_setattroЭто поле наследуется подтипами вместе с
tp_setattr: подтип наследует оба поляtp_setattrиtp_setattroот базового типа, когдаtp_setattrиtp_setattroподтипа обаNULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericSetAttr().
-
PyBufferProcs* PyTypeObject.tp_as_buffer -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют интерфейс буфера. Эти поля документированы в Структуры объектов буфера.
Наследование:
Поле
tp_as_bufferне наследуется, но содержащиеся в нем поля наследуются индивидуально.
-
unsigned long PyTypeObject.tp_flags -
Это поле представляет собой битовую маску различных флагов. Некоторые флаги указывают на варианты семантики в определённых ситуациях; другие используются для обозначения того, что определённые поля в объекте типа (или в структурах расширения, на которые ссылаются
tp_as_number,tp_as_sequence,tp_as_mappingиtp_as_buffer), которые исторически не всегда присутствовали, являются допустимыми; если такой бит флага сброшен, поля типа, которые он защищает, не должны быть обращены и должны рассматриваться как имеющие нулевое илиNULLзначение.Наследование:
Наследование этого поля сложно. Большинство битов флагов наследуются индивидуально, т.е. если базовый тип имеет установленный бит флага, подтип наследует этот бит флага. Бит флага, относящийся к структурам расширения, строго наследуется, если структура расширения наследуется, т.е. значение бита флага базового типа копируется в подтип вместе с указателем на структуру расширения. Бит флага
Py_TPFLAGS_HAVE_GCнаследуется вместе с полямиtp_traverseиtp_clear, т.е. если бит флагаPy_TPFLAGS_HAVE_GCсброшен в подтипе, и поляtp_traverseиtp_clearв подтипе существуют и имеютNULLзначения.По умолчанию:
PyBaseObject_TypeиспользуетPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.Битовые маски:
В настоящее время определены следующие битовые маски; эти маски могут быть объединены с помощью оператора
|для формирования значения поляtp_flags. МакросPyType_HasFeature()принимает тип и значение флагов, tp и f, и проверяет, является лиtp->tp_flags & fненулевым.-
Py_TPFLAGS_HEAPTYPE -
Этот бит устанавливается, когда сам объект типа выделяется в куче, например, типы, созданные динамически с помощью
PyType_FromSpec(). В этом случае полеob_typeего экземпляров считается ссылкой на тип, и объект типа INCREF'ится при создании нового экземпляра, и DECREF'ится при уничтожении экземпляра (это не относится к экземплярам подтипов; только тип, на который ссылается ob_type экземпляра, получает INCREF' или DECREF').Наследование:
???
-
Py_TPFLAGS_BASETYPE -
Этот бит устанавливается, когда тип может использоваться как базовый тип другого типа. Если этот бит сброшен, тип не может быть подтипом (аналогично классу "final" в Java).
Наследование:
???
-
Py_TPFLAGS_READY -
Этот бит устанавливается, когда объект типа был полностью инициализирован функцией
PyType_Ready().Наследование:
???
-
Py_TPFLAGS_READYING -
Этот бит устанавливается, пока
PyType_Ready()находится в процессе инициализации объекта типа.Наследование:
???
-
Py_TPFLAGS_HAVE_GC -
Этот бит устанавливается, когда объект поддерживает сборку мусора. Если этот бит установлен, экземпляры должны создаваться с помощью
PyObject_GC_New()и уничтожаться с помощьюPyObject_GC_Del(). Дополнительная информация в разделе Поддержка циклического сбора мусора. Этот бит также подразумевает, что поля, связанные с GC,tp_traverseиtp_clear, присутствуют в объекте типа.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearБит флага
Py_TPFLAGS_HAVE_GCнаследуется вместе с полямиtp_traverseиtp_clear, т.е. если бит флагаPy_TPFLAGS_HAVE_GCсброшен в подтипе, и поляtp_traverseиtp_clearв подтипе существуют и имеютNULLзначения.
-
Py_TPFLAGS_DEFAULT -
Это битовая маска всех битов, относящихся к существованию определенных полей в объекте типа и его структурах расширения. В настоящее время она включает следующие биты:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION,Py_TPFLAGS_HAVE_VERSION_TAG.Наследование:
???
-
Py_TPFLAGS_METHOD_DESCRIPTOR -
Этот бит указывает, что объекты ведут себя как несвязанные методы.
Если этот флаг установлен для
type(meth), то:-
meth.__get__(obj, cls)(*args, **kwds)(сobjне равным None) должно быть эквивалентноmeth(obj, *args, **kwds). -
meth.__get__(None, cls)(*args, **kwds)должно быть эквивалентноmeth(*args, **kwds).
Этот флаг позволяет оптимизировать обычные вызовы методов, такие как
obj.meth(), - он избегает создания временного объекта «связанного метода» дляobj.meth.Введено в версии 3.8.
Наследование:
Этот флаг никогда не наследуется типами кучи. Для типов расширений он наследуется всякий раз, когда
tp_descr_getнаследуется. -
-
Py_TPFLAGS_LONG_SUBCLASS
-
Py_TPFLAGS_LIST_SUBCLASS
-
Py_TPFLAGS_TUPLE_SUBCLASS
-
Py_TPFLAGS_BYTES_SUBCLASS
-
Py_TPFLAGS_UNICODE_SUBCLASS
-
Py_TPFLAGS_DICT_SUBCLASS
-
Py_TPFLAGS_BASE_EXC_SUBCLASS
-
Py_TPFLAGS_TYPE_SUBCLASS -
Эти флаги используются функциями, такими как
PyLong_Check(), для быстрого определения, является ли тип подклассом встроенного типа; такие проверки специфичнее, чем общая проверка, например,PyObject_IsInstance(). Пользовательские типы, наследующие от встроенных, должны иметь соответствующее значениеtp_flags, в противном случае код, взаимодействующий с такими типами, будет вести себя иначе, в зависимости от используемой проверки.
-
Py_TPFLAGS_HAVE_FINALIZE -
Этот бит устанавливается, когда слот
tp_finalizeприсутствует в структуре типа.Введено в версии 3.4.
Устарело начиная с версии 3.8: Этот флаг больше не нужен, поскольку интерпретатор предполагает, что слот
tp_finalizeвсегда присутствует в структуре типа.
-
_Py_TPFLAGS_HAVE_VECTORCALL -
Этот бит устанавливается, когда класс реализует протокол vectorcall. Подробности см. в
tp_vectorcall_offset.Наследование:
Этот бит устанавливается для статических подтипов, если
tp_flagsне переопределён: подтип наследует_Py_TPFLAGS_HAVE_VECTORCALLот базового типа, когдаtp_callподтипа равенNULLиPy_TPFLAGS_HEAPTYPEподтипа не установлен.Типы кучи не наследуют
_Py_TPFLAGS_HAVE_VECTORCALL.Примечание
Этот флаг предварительный и ожидается, что он станет общедоступным в Python 3.9, с другим именем и, возможно, изменённой семантикой. Если вы используете vectorcall, подготовьтесь к обновлению своего кода для Python 3.9.
Введено в версии 3.8.
-
-
const char* PyTypeObject.tp_doc -
Необязательный указатель на завершающую нулём строку C, содержащую строку документации для данного объекта типа. Это отображается как атрибут
__doc__в типе и экземплярах типа.Наследование:
Это поле не наследуется подтипами.
-
traverseproc PyTypeObject.tp_traverse -
Необязательный указатель на функцию обхода для сборщика мусора. Используется только если установлен флаг
Py_TPFLAGS_HAVE_GC. Подпись функции:int tp_traverse(PyObject *self, visitproc visit, void *arg);
Дополнительную информацию о схеме сборки мусора Python см. в разделе Поддержка циклической сборки мусора.
Указатель
tp_traverseиспользуется сборщиком мусора для обнаружения циклов ссылок. Типичная реализация функцииtp_traverseпросто вызываетPy_VISIT()для каждого члена экземпляра, являющегося объектом Python, который владеет экземпляр. Например, эта функцияlocal_traverse()из расширения модуля_thread:static int local_traverse(localobject *self, visitproc visit, void *arg) { Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }Обратите внимание, что
Py_VISIT()вызывается только для тех членов, которые могут участвовать в циклах ссылок. Хотя есть и членself->key, он может быть толькоNULLили строкой Python и, следовательно, не может быть частью цикла ссылок.С другой стороны, даже если вы знаете, что член никогда не может быть частью цикла, в качестве средства отладки вы можете посетить его, чтобы функция
gcмодуляget_referents()включила его.Предупреждение
При реализации
tp_traverseследует посещать только те члены, которыми экземпляр владеет (имея сильные ссылки на них). Например, если объект поддерживает слабые ссылки через слотtp_weaklist, указатель, поддерживающий связанный список (на что указывает tp_weaklist), не должен посещаться, так как экземпляр не владеет напрямую слабыми ссылками на себя (список слабых ссылок предназначен для поддержки механизма слабых ссылок, но экземпляр не имеет сильной ссылки на элементы внутри него, поскольку они могут быть удалены, даже если экземпляр всё ещё жив).Обратите внимание, что
Py_VISIT()требует, чтобы параметры visit и arg функцииlocal_traverse()имели эти конкретные имена; не присваивайте им просто любые имена.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭто поле наследуется подтипами вместе с
tp_clearи флагомPy_TPFLAGS_HAVE_GC: сам флаг,tp_traverseиtp_clearнаследуются от базового типа, если все они равны нулю в подтипе.
-
inquiry PyTypeObject.tp_clear -
Необязательный указатель на функцию очистки для сборщика мусора. Используется только если установлен флаг
Py_TPFLAGS_HAVE_GC. Подпись функции:int tp_clear(PyObject *);
Функция
tp_clearиспользуется для разрыва циклов ссылок в циклических мусорных объектах, обнаруженных сборщиком мусора. В совокупности все функцииtp_clearв системе должны объединяться для разрыва всех циклов ссылок. Это тонкий момент, и при сомнениях следует предоставить функциюtp_clear. Например, тип кортежей не реализует функциюtp_clear, потому что можно доказать, что ни один цикл ссылки не может быть полностью составлен из кортежей. Поэтому функцииtp_clearдругих типов должны быть достаточными для разрыва любого цикла, содержащего кортеж. Это не очевидно сразу, и редко есть веские причины избегать реализацииtp_clear.Реализации функций
tp_clearдолжны прерывать ссылки экземпляра на его члены, которые могут быть объектами Python, и установить указатели на эти члены в значениеNULL, как в следующем примере:static int local_clear(localobject *self) { Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }Следует использовать макрос
Py_CLEAR(), потому что очистка ссылок требует внимания: ссылка на содержащий объект не должна уменьшаться до тех пор, пока указатель на содержащий объект не будет установлен в значениеNULL. Это связано с тем, что уменьшение счётчика ссылок может привести к тому, что содержащий объект станет мусором, вызвав цепочку действий по освобождению, которые могут включать вызов произвольного кода Python (из-за финализаторов или обратных вызовов weakref, связанных с содержащим объектом). Если такой код может снова ссылаться на self, важно, чтобы указатель на содержащий объект былNULLв этот момент, чтобы self знал, что содержащий объект больше нельзя использовать. МакросPy_CLEAR()выполняет операции в безопасном порядке.Поскольку цель функций
tp_clearзаключается в разрыве циклов ссылок, нет необходимости очищать содержащиеся объекты, такие как строки Python или целые числа Python, которые не могут участвовать в циклах ссылок. С другой стороны, может быть удобно очищать все содержащиеся объекты Python и писать функциюtp_deallocтипа для вызова функцииtp_clear.Дополнительную информацию о схеме сборки мусора Python см. в разделе Поддержка циклической сборки мусора.
Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭто поле наследуется подтипами вместе с
tp_traverseи флагомPy_TPFLAGS_HAVE_GC: сам флаг,tp_traverseиtp_clearнаследуются от базового типа, если все они равны нулю в подтипе.
-
richcmpfunc PyTypeObject.tp_richcompare -
Необязательный указатель на функцию сравнения, сигнатура которой:
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
Первый параметр гарантированно является экземпляром типа, определённого в
PyTypeObject.Функция должна вернуть результат сравнения (обычно
Py_TrueилиPy_False). Если сравнение не определено, она должна вернутьPy_NotImplemented, в случае другой ошибки —NULL, при этом необходимо установить условие исключения.Ниже определены константы, используемые в качестве третьего аргумента для
tp_richcompareиPyObject_RichCompare():Константа
Сравнение
Py_LT<Py_LE<=Py_EQ==Py_NE!=Py_GT>Py_GE>=Для упрощения написания функций сравнения определена следующая макрокоманда:
-
Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op) -
Возвращает
Py_TrueилиPy_Falseиз функции, в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочиваемы операторами C-сравнения (например, это могут быть C-целые числа или числа с плавающей точкой). Третий аргумент указывает на запрашиваемую операцию, как дляPyObject_RichCompare().Счётчик ссылок возвращаемого значения увеличивается корректно.
При ошибке устанавливает исключение и возвращает
NULLиз функции.Добавлена в версии 3.7.
Наследование:
Группа:
tp_hash,tp_richcompareЭто поле наследуется подтипами вместе с
tp_hash: подтип наследуетtp_richcompareиtp_hash, когда у подтипаtp_richcompareиtp_hashоба равныNULL.По умолчанию:
PyBaseObject_Typeпредоставляет реализациюtp_richcompare, которая может быть унаследована. Однако, если определён толькоtp_hash, не используется даже унаследованная функция, и экземпляры типа не смогут участвовать в каких-либо сравнениях. -
-
Py_ssize_t PyTypeObject.tp_weaklistoffset -
Если экземпляры этого типа могут быть слабо ссылаемыми, это поле больше нуля и содержит смещение в структуре экземпляра заголовка списка слабых ссылок (игнорируя заголовок сборки мусора, если он присутствует); это смещение используется
PyObject_ClearWeakRefs()и функциямиPyWeakref_*(). Структура экземпляра должна включать поле типаPyObject*, инициализированноеNULL.Не путать это поле с
tp_weaklist; это заголовок списка слабых ссылок на сам объект типа.Наследование:
Это поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить это смещение; это означает, что подтип использует другой заголовок списка слабых ссылок, чем базовый тип. Поскольку заголовок списка всегда находится через
tp_weaklistoffset, это не должно вызывать проблем.Когда тип, определённый инструкцией класса, не имеет объявления
__slots__, и ни один из его базовых типов не является слабо ссылаемым, тип делается слабо ссылаемым путём добавления в расположение экземпляра заголовка списка слабых ссылок и установкиtp_weaklistoffsetдля смещения этого заголовка.Когда объявление
__slots__типа содержит слот с именем__weakref__, этот слот становится заголовком списка слабых ссылок для экземпляров типа, а смещение слота сохраняется вtp_weaklistoffsetтипа.Когда объявление
__slots__типа не содержит слота с именем__weakref__, тип наследует своёtp_weaklistoffsetот своего базового типа.
-
getiterfunc PyTypeObject.tp_iter -
Необязательный указатель на функцию, возвращающую итератор для объекта. Его наличие обычно означает, что экземпляры этого типа итерируемые (хотя последовательности могут быть итерируемыми и без этой функции).
Эта функция имеет ту же сигнатуру, что и
PyObject_GetIter():PyObject *tp_iter(PyObject *self);
Наследование:
Это поле наследуется подтипами.
-
iternextfunc PyTypeObject.tp_iternext -
Необязательный указатель на функцию, возвращающую следующий элемент в итераторе. Сигнатура:
PyObject *tp_iternext(PyObject *self);
Когда итератор исчерпан, она должна вернуть
NULL; исключениеStopIterationможет быть или нет установлено. При возникновении другой ошибки она также должна вернутьNULL. Его наличие сигнализирует, что экземпляры этого типа являются итераторами.Типы итераторов также должны определять функцию
tp_iter, и эта функция должна возвращать сам экземпляр итератора (а не новый экземпляр итератора).Эта функция имеет ту же сигнатуру, что и
PyIter_Next().Наследование:
Это поле наследуется подтипами.
-
struct PyMethodDef* PyTypeObject.tp_methods -
Необязательный указатель на статический массив, завершённый
NULL, структурPyMethodDef, объявляющих обычные методы этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель метода.Наследование:
Это поле не наследуется подтипами (методы наследуются по другому механизму).
-
struct PyMemberDef* PyTypeObject.tp_members -
Необязательный указатель на статический массив, завершённый
NULL, структурPyMemberDef, объявляющих обычные данные членов (поля или слоты) экземпляров этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель члена.Наследование:
Это поле не наследуется подтипами (члены наследуются по другому механизму).
-
struct PyGetSetDef* PyTypeObject.tp_getset -
Необязательный указатель на статический массив, завершённый
NULL, структурPyGetSetDef, объявляющих вычисляемые атрибуты экземпляров этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель getset.Наследование:
Это поле не наследуется подтипами (вычисляемые атрибуты наследуются по другому механизму).
-
PyTypeObject* PyTypeObject.tp_base -
Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа путем вызова метатипа.
Примечание
Инициализация слотов подчиняется правилам инициализации глобальных переменных. C99 требует, чтобы инициализаторы были «константами адресов». Указатели на функции, такие как
PyType_GenericNew(), с неявным преобразованием в указатель, являются допустимыми константами адресов C99.Однако унарный оператор ‘&’ примененный к нестатической переменной, такой как
PyBaseObject_Type(), не обязан производить константу адреса. Компиляторы могут поддерживать это (gcc поддерживает), MSVC — нет. Оба компилятора строго соответствуют стандарту в этом поведении.Следовательно,
tp_baseдолжен быть установлен в функции инициализации расширения модуля.Наследование:
Это поле не наследуется подтипами (очевидно).
Значение по умолчанию:
Это поле по умолчанию устанавливается в значение
&PyBaseObject_Type(которое для программистов Python известно как типobject).
-
PyObject* PyTypeObject.tp_dict -
Словарь типа хранится здесь функцией
PyType_Ready().Это поле обычно должно быть инициализировано значением
NULLперед вызовом PyType_Ready; оно также может быть инициализировано словарем, содержащим начальные атрибуты типа. После того, какPyType_Ready()инициализировала тип, дополнительные атрибуты для типа могут быть добавлены в этот словарь только если они не соответствуют перегруженным операциям (таким как__add__()).Наследование:
Это поле не наследуется подтипами (хотя атрибуты, определенные здесь, наследуются через другой механизм).
Значение по умолчанию:
Если это поле равно
NULL,PyType_Ready()присвоит ему новый словарь.Предупреждение
Небезопасно использовать
PyDict_SetItem()на словареtp_dictили иным образом изменять его с помощью функций C-API словаря.
-
descrgetfunc PyTypeObject.tp_descr_get -
Необязательный указатель на функцию «получения дескриптора».
Подпись функции:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
Наследование:
Это поле наследуется подтипами.
-
descrsetfunc PyTypeObject.tp_descr_set -
Необязательный указатель на функцию для установки и удаления значения дескриптора.
Подпись функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Аргумент value устанавливается в
NULLдля удаления значения.Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_dictoffset -
Если экземпляры данного типа имеют словарь, содержащий переменные экземпляра, это поле отлично от нуля и содержит смещение в структуре экземпляров типа для словаря переменных экземпляра; это смещение используется функцией
PyObject_GenericGetAttr().Не путайте это поле с
tp_dict; это словарь атрибутов самого объекта типа.Если значение этого поля больше нуля, оно определяет смещение от начала структуры экземпляра. Если значение меньше нуля, оно определяет смещение от конца структуры экземпляра. Отрицательное смещение более дорогостоящее в использовании и должно использоваться только в случаях, когда структура экземпляра содержит часть переменной длины. Это используется, например, для добавления словаря переменных экземпляра к подтипам
strилиtuple. Обратите внимание, что полеtp_basicsizeдолжно учитывать добавленный словарь в конце в этом случае, даже если словарь не включен в основной макет объекта. В системе с размером указателя 4 байтаtp_dictoffsetдолжно быть установлено в-4для обозначения расположения словаря в самом конце структуры.Действительное смещение словаря в экземпляре может быть вычислено из отрицательного
tp_dictoffsetследующим образом:dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset if dictoffset is not aligned on sizeof(void*): round up to sizeof(void*)где
tp_basicsize,tp_itemsizeиtp_dictoffsetберутся из объекта типа, аob_size— из экземпляра. Знак абсолютной величины берется, потому что целые числа используют знакob_sizeдля хранения знака числа. (Вам никогда не потребуется выполнять это вычисление самостоятельно; оно выполняется для вас функцией_PyObject_GetDictPtr().)Наследование:
Это поле наследуется подтипами, но см. правила ниже. Подтип может переопределить это смещение; это означает, что экземпляры подтипа хранят словарь по другому смещению, чем базовый тип. Поскольку словарь всегда находится с помощью
tp_dictoffset, это не должно быть проблемой.Когда тип, определенный оператором class, не имеет объявления
__slots__и ни один из его базовых типов не имеет словаря переменных экземпляра, к макету экземпляра добавляется слот словаря, иtp_dictoffsetустанавливается в смещение этого слота.Когда тип, определенный оператором class, имеет объявление
__slots__, тип наследуетtp_dictoffsetот своего базового типа.(Добавление слота с именем
__dict__к объявлению__slots__не дает ожидаемого результата, это просто создает путаницу. Возможно, это должно быть добавлено как функция, так же как и__weakref__)Значение по умолчанию:
Этот слот не имеет значения по умолчанию. Для статических типов, если поле равно
NULL, для экземпляров не создается__dict__.
-
initproc PyTypeObject.tp_init -
Необязательный указатель на функцию инициализации экземпляра.
Эта функция соответствует методу
__init__()классов. Как и__init__(), возможно создание экземпляра без вызова__init__(), и возможно повторная инициализация экземпляра путем повторного вызова его метода__init__().Подпись функции:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
Аргумент self — это экземпляр, который необходимо инициализировать; аргументы args и kwds представляют позиционные и ключевые аргументы вызова
__init__().Функция
tp_init, если она неNULL, вызывается при создании экземпляра стандартным способом путем вызова его типа, после того, как функция типаtp_newвернула экземпляр типа. Если функцияtp_newвозвращает экземпляр другого типа, который не является подтипом исходного типа, функцияtp_initне вызывается; еслиtp_newвозвращает экземпляр подтипа исходного типа, вызывается функцияtp_initподтипа.Возвращает
0при успехе,-1и устанавливает исключение при ошибке.Наследование:
Это поле наследуется подтипами.
Значение по умолчанию:
Для статических типов это поле не имеет значения по умолчанию.
-
allocfunc PyTypeObject.tp_alloc -
Необязательный указатель на функцию выделения экземпляра.
Подпись функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса).
Значение по умолчанию:
Для динамических подтипов это поле всегда устанавливается в
PyType_GenericAlloc(), чтобы принудительно использовать стандартную стратегию выделения памяти.Для статических подтипов
PyBaseObject_TypeиспользуетPyType_GenericAlloc(). Это рекомендуемое значение для всех статически определенных типов.
-
newfunc PyTypeObject.tp_new -
Необязательный указатель на функцию создания экземпляра.
Подпись функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент подтип — это тип создаваемого объекта; аргументы args и kwds представляют позиционные и именованные аргументы вызова типа. Обратите внимание, что подтип не обязательно должен быть равен типу, функция
tp_newкоторого вызывается; он может быть подтипом этого типа (но не несвязанным типом).Функция
tp_newдолжна вызватьsubtype->tp_alloc(subtype, nitems)для выделения памяти под объект, а затем выполнить только необходимую инициализацию. Инициализацию, которую можно безопасно пропустить или повторить, следует поместить в обработчикtp_init. Хорошим правилом является то, что для неизменяемых типов вся инициализация должна происходить вtp_new, а для изменяемых типов большая часть инициализации должна быть отложена доtp_init.Наследование:
Это поле наследуется подтипами, за исключением статических типов, у которых
tp_baseравноNULLили&PyBaseObject_Type.Значение по умолчанию:
Для статических типов это поле не имеет значения по умолчанию. Это означает, что если слот определен как
NULL, тип не может вызываться для создания новых экземпляров; предположительно, есть другой способ создания экземпляров, например, с помощью функции-фабрики.
-
freefunc PyTypeObject.tp_free -
Необязательный указатель на функцию освобождения экземпляра. Подпись функции:
void tp_free(void *self);
Инициализатор, совместимый с этой подписью, — это
PyObject_Free().Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса).
Значение по умолчанию:
В динамических подтипах это поле устанавливается в деаллокатор, подходящий для
PyType_GenericAlloc()и значения бита флагаPy_TPFLAGS_HAVE_GC.Для статических подтипов
PyBaseObject_Typeиспользует PyObject_Del.
-
inquiry PyTypeObject.tp_is_gc -
Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщику мусора нужно знать, является ли конкретный объект собираемым. Обычно достаточно посмотреть на поле
tp_flagsтипа объекта и проверить бит флагаPy_TPFLAGS_HAVE_GC. Но некоторые типы имеют смесь статически и динамически выделенных экземпляров, и статически выделенные экземпляры не собираются. Такие типы должны определить эту функцию; она должна возвращать1для собираемого экземпляра и0для несобираемого экземпляра. Подпись функции:int tp_is_gc(PyObject *self);
(Единственным примером этого являются типы сами по себе. Метатип,
PyType_Type, определяет эту функцию для различения статически и динамически выделенных типов.)Наследование:
Это поле наследуется подтипами.
Значение по умолчанию:
Этот слот не имеет значения по умолчанию. Если это поле
NULL,Py_TPFLAGS_HAVE_GCиспользуется в качестве функционального эквивалента.
-
PyObject* PyTypeObject.tp_bases -
Кортеж базовых типов.
Это устанавливается для типов, созданных оператором класса. Для статически определенных типов это должно быть
NULL.Наследование:
Это поле не наследуется.
-
PyObject* PyTypeObject.tp_mro -
Кортеж, содержащий расширенный набор базовых типов, начиная с самого типа и заканчивая
object, в порядке разрешения методов.Наследование:
Это поле не наследуется; оно вычисляется заново функцией
PyType_Ready().
-
PyObject* PyTypeObject.tp_cache -
Не используется. Использование только внутри.
Наследование:
Это поле не наследуется.
-
PyObject* PyTypeObject.tp_subclasses -
Список слабых ссылок на подклассы. Использование только внутри.
Наследование:
Это поле не наследуется.
-
PyObject* PyTypeObject.tp_weaklist -
Голова списка слабых ссылок для слабых ссылок на этот объект типа. Не наследуется. Использование только внутри.
Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_del -
Это поле устарело. Используйте
tp_finalizeвместо него.
-
unsigned int PyTypeObject.tp_version_tag -
Используется для индексирования в кэше методов. Использование только внутри.
Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_finalize -
Необязательный указатель на функцию завершения экземпляра. Подпись функции:
void tp_finalize(PyObject *self);
Если
tp_finalizeустановлен, интерпретатор вызывает его один раз при завершении экземпляра. Он вызывается либо из сборщика мусора (если экземпляр является частью изолированного цикла ссылок), либо непосредственно перед освобождением объекта. В любом случае гарантируется, что он будет вызван перед попыткой разорвать циклы ссылок, обеспечивая, что он найдет объект в нормальном состоянии.tp_finalizeне должен изменять текущее состояние исключения; поэтому рекомендуемый способ написания нетривиального завершителя:static void local_finalize(PyObject *self) { PyObject *error_type, *error_value, *error_traceback; /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); /* ... */ /* Restore the saved exception. */ PyErr_Restore(error_type, error_value, error_traceback); }Чтобы это поле учитывалось (даже через наследование), необходимо также установить бит флага
Py_TPFLAGS_HAVE_FINALIZE.Наследование:
Это поле наследуется подтипами.
Добавлен в версии 3.4.
См. также
“Безопасная финализация объектов” (PEP 442)
Остальные поля определены только в том случае, если макрос проверки функции COUNT_ALLOCS определен, и предназначены только для внутреннего использования. Они документированы здесь для полноты. Ни одно из этих полей не наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_allocs -
Количество выделений.
-
Py_ssize_t PyTypeObject.tp_frees -
Количество освобождений.
-
Py_ssize_t PyTypeObject.tp_maxalloc -
Максимальное количество одновременно выделенных объектов.
-
PyTypeObject* PyTypeObject.tp_prev -
Указатель на предыдущий объект типа с ненулевым полем
tp_allocs.
-
PyTypeObject* PyTypeObject.tp_next -
Указатель на следующий объект типа с ненулевым полем
tp_allocs.
Также обратите внимание, что в Python со сборкой мусора tp_dealloc может вызываться из любого потока Python, а не только из того, который создал объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Это не проблема для вызовов Python API, так как поток, в котором вызывается tp_dealloc, владеет глобальной блокировкой интерпретатора (GIL). Однако если уничтожаемый объект в свою очередь уничтожает объекты из какой-либо другой библиотеки C или C++, необходимо позаботиться о том, чтобы уничтожение этих объектов в потоке, вызвавшем tp_dealloc, не нарушало никаких предположений библиотеки.
Типы кучи
Традиционно, типы, определённые в коде C, являются статическими, то есть, структура PyTypeObject является статической и определяется непосредственно в коде, инициализируясь с помощью PyType_Ready().
Это приводит к типам, ограниченным по сравнению с типами, определёнными в Python:
- Статические типы ограничены одним базовым типом, т.е. они не могут использовать множественное наследование.
- Объекты статических типов (но не обязательно их экземпляры) являются неизменяемыми. Добавить или изменить атрибуты объекта типа из Python невозможно.
- Объекты статических типов совместно используются между под-интерпретаторами, поэтому они не должны включать в себя какие-либо состояния, специфичные для под-интерпретатора.
Также, поскольку PyTypeObject не входит в состав стабильной ABI, любые модули расширения, использующие статические типы, должны быть скомпилированы для конкретной младшей версии Python.
Альтернативой статическим типам являются типы, выделяемые в куче, или коротко типы кучи, которые тесно соответствуют классам, созданным в Python с помощью class оператора.
Это делается путем заполнения структуры PyType_Spec и вызова PyType_FromSpecWithBases().
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/c-api/typeobj.html