Объекты типов
Возможно, одной из самых важных структур системы объектов Python является структура, определяющая новый тип: структура PyTypeObject. Объекты типов могут обрабатываться с помощью любых функций PyObject_* или PyType_*, но не предлагают ничего интересного для большинства приложений Python. Эти объекты фундаментальны для поведения объектов, поэтому они очень важны для самого интерпретатора и для любого модуля расширения, реализующего новые типы.
Объекты типов довольно велики по сравнению с большинством стандартных типов. Причина такого размера в том, что каждый объект типа хранит большое количество значений, в основном указатели на C-функции, каждая из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно рассматриваются в этом разделе. Поля будут описаны в том порядке, в котором они встречаются в структуре.
В дополнение к следующей краткой справке, раздел Примеры предоставляет краткий обзор смысла и использования PyTypeObject.
Быстрое справочное руководство
“tp slots”
Раздел 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__ | ~ | |||
[ |
| |||||
| __subclasses__ | |||||
| ||||||
( | ||||||
unsigned int | ||||||
__del__ | X | |||||
-
1 -
(): Имя слота в скобках указывает, что оно (эффективно) устарело.
<>: Имена в угловых скобках должны быть первоначально установлены в
NULLи обрабатываться как только для чтения.[]: Имена в квадратных скобках предназначены только для внутреннего использования.
<R> (в качестве префикса) означает, что поле обязательно (должно быть отличным от
NULL). -
2 -
Столбцы:
“O”: устанавливается на
PyBaseObject_Type“T”: устанавливается на
PyType_Type“D”: значение по умолчанию (если слот установлен на
NULL)X - PyType_Ready sets this value if it is NULL ~ - PyType_Ready always sets this value (it should be NULL) ? - PyType_Ready may set this value depending on other slots Also see the inheritance column ("I").“I”: наследование
X - type slot is inherited via *PyType_Ready* if defined with a *NULL* value % - the slots of the sub-struct are inherited individually G - inherited, but only in combination with other slots; see the slot's description ? - it's complicated; see the slot's description
Обратите внимание, что некоторые слоты фактически наследуются через обычную цепочку поиска атрибутов.
под-слоты
Слот | специальные методы | |
|---|---|---|
__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__ | ||
типы слотов
typedef | Типы параметров | Тип возвращаемого значения |
|---|---|---|
| ||
void * | void | |
void * | void | |
int | ||
| ||
int | ||
|
| |
| ||
int | ||
| ||
int | ||
| ||
int | ||
| Py_hash_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 */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
// Strong reference on a heap type, borrowed reference on a static type
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag;
destructor tp_finalize;
vectorcallfunc tp_vectorcall;
} PyTypeObject;
Слоты PyObject
Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (созданных type_new(), обычно из оператора класса). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, что означает, что его экземпляры (то есть объекты типа) должны иметь поле ob_size.
-
Py_ssize_t PyObject.ob_refcnt -
Часть Стабильной ABI.
Это счётчик ссылок объекта типа, инициализированный макросом
PyObject_HEAD_INITзначением1. Обратите внимание, что для статически выделенных объектов типа экземпляры типа (объекты, чьё полеob_typeуказывает на тип) не учитываются как ссылки. Но для динамически выделенных объектов типа экземпляры учитываются как ссылки.Наследование:
Это поле не наследуется подтипами.
-
PyTypeObject *PyObject.ob_type -
Часть Стабильной ABI.
Это тип типа, другими словами, его метатип. Он инициализируется аргументом макроса
PyObject_HEAD_INIT, и его значение обычно должно быть&PyType_Type. Однако, для динамически загружаемых модулей расширений, которые должны работать в Windows (по крайней мере), компилятор жалуется, что это не допустимое начальное значение. Поэтому принято передаватьNULLмакросуPyObject_HEAD_INITи явно инициализировать это поле в начале функции инициализации модуля, прежде чем делать что-либо ещё. Это обычно делается так:Foo_Type.ob_type = &PyType_Type;
Это должно быть сделано до создания каких-либо экземпляров типа.
PyType_Ready()проверяет, является лиob_typeравнымNULL, и если да, инициализирует его значением поляob_typeбазового класса.PyType_Ready()не будет изменять это поле, если оно не равно нулю.Наследование:
Это поле наследуется подтипами.
-
PyObject *PyObject._ob_next -
PyObject *PyObject._ob_prev -
Эти поля присутствуют только при определении макроса
Py_TRACE_REFS(см.configure --with-trace-refs option).Их инициализация значением
NULLосуществляется макросомPyObject_HEAD_INIT. Для статически выделенных объектов эти поля всегда остаютсяNULL. Для динамически выделенных объектов эти два поля используются для связывания объекта в двусвязный список всех живых объектов на куче.Это может использоваться для различных целей отладки; в настоящее время единственное использование — функция
sys.getobjects()и вывод объектов, которые всё ещё живы в конце выполнения, когда переменная окруженияPYTHONDUMPREFSустановлена.Наследование:
Эти поля не наследуются подтипами.
Слоты PyVarObject
-
Py_ssize_t PyVarObject.ob_size -
Часть Стабильной ABI.
Для статически выделенных объектов типа это значение должно быть равно нулю. Для динамически выделенных объектов типа это поле имеет специальное внутреннее значение.
Наследование:
Это поле не наследуется подтипами.
Слот объекта PyTypeObject
Каждый слот имеет раздел, описывающий наследование. Если PyType_Ready() может установить значение, когда поле установлено в NULL, тогда также будет раздел «Значение по умолчанию». (Обратите внимание, что многие поля, установленные на PyBaseObject_Type и PyType_Type, фактически действуют как значения по умолчанию.)
-
const char *PyTypeObject.tp_name -
Указатель на строку с завершающим нулем, содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, за которым следует точка, за которой следует имя типа; для встроенных типов она должна содержать только имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип с именем
T, определенный в модулеMв подпакетеQв пакетеPдолжен иметь инициализаторtp_name"P.Q.M.T".Для динамически выделенных объектов типа это должно быть просто имя типа, а имя модуля явно хранится в словаре типа в качестве значения для ключа
'__module__'.Для статически выделенных объектов типа, поле tp_name должно содержать точку. Всё перед последней точкой делается доступным как атрибут
__module__, а всё после последней точки делается доступным как атрибут__name__.Если точка отсутствует, всё поле
tp_nameделается доступным как атрибут__name__, а атрибут__module__не определен (если явно не установлен в словаре, как описано выше). Это означает, что ваш тип будет невозможно сериализовать. Кроме того, он не будет отображаться в документации модулей, созданных с помощью pydoc.Это поле не должно быть
NULL. Это единственное обязательное поле вPyTypeObject()(кроме потенциальноtp_itemsize).Наследование:
Это поле не наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_basicsize -
Py_ssize_t PyTypeObject.tp_itemsize -
Эти поля позволяют вычислить размер в байтах экземпляров типа.
Существуют два типа типов: типы с экземплярами фиксированной длины имеют поле
tp_itemsizeравное нулю, типы с экземплярами переменной длины имеют полеtp_itemsize, отличное от нуля. Для типа с экземплярами фиксированной длины все экземпляры имеют одинаковый размер, указанный вtp_basicsize.Для типа с экземплярами переменной длины экземпляры должны иметь поле
ob_size, а размер экземпляра составляетtp_basicsizeплюс N разtp_itemsize, где N — «длина» объекта. Значение N обычно хранится в поле экземпляраob_size.Существуют исключения: например, целые числа используют отрицательное
ob_sizeдля указания отрицательного числа, и N —abs(ob_size)в этом случае.Наличие поля
ob_sizeв структуре экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура типа списка имеет экземпляры фиксированной длины, но эти экземпляры имеют осмысленное полеob_size).Базовый размер включает поля в экземпляре, объявленные макросом
PyObject_HEADилиPyObject_VAR_HEAD(в зависимости от того, какой используется для объявления структуры экземпляра) и это, в свою очередь, включает поля_ob_prevи_ob_nextесли они присутствуют. Это означает, что единственный правильный способ получить инициализатор дляtp_basicsize— использование оператораsizeofна структуре, используемой для объявления структуры экземпляра. Базовый размер не включает размер заголовка сборки мусора.Замечание об выравнивании: если переменные элементы требуют определённого выравнивания, это должно быть учтено значением
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_HAVE_GC), деструктор должен вызватьPyObject_GC_UnTrack()перед очисткой любых членских полей.static void foo_dealloc(foo_object *self) { PyObject_GC_UnTrack(self); Py_CLEAR(self->ref); Py_TYPE(self)->tp_free((PyObject *)self); }Наконец, если тип выделен в куче (
Py_TPFLAGS_HEAPTYPE), деаллокатор должен освободить владение типом объекта (черезPy_DECREF()) после вызова деаллокатора типа. Для предотвращения подвешенных указателей рекомендуемый способ сделать это следующий:static void foo_dealloc(foo_object *self) { PyTypeObject *tp = Py_TYPE(self); // free references and buffers here tp->tp_free(self); Py_DECREF(tp); }Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset -
Необязательный смещение к функции на экземпляре, которая реализует вызов объекта с помощью протокола протокола vectorcall, более эффективной альтернативы простому
tp_call.Это поле используется только если установлен флаг
Py_TPFLAGS_HAVE_VECTORCALL. В этом случае это должно быть положительное целое число, содержащее смещение в экземпляре указателяvectorcallfunc.Указатель vectorcallfunc может быть
NULL, в этом случае экземпляр ведет себя так, как если быPy_TPFLAGS_HAVE_VECTORCALLне был установлен: вызов экземпляра переходит кtp_call.Любой класс, который устанавливает
Py_TPFLAGS_HAVE_VECTORCALL, должен также установитьtp_callи убедиться, что его поведение согласуется с функцией vectorcallfunc. Это можно сделать, установив tp_call наPyVectorcall_Call().Предупреждение
Не рекомендуется для типов кучи реализовывать протокол vectorcall. Когда пользователь устанавливает
__call__в коде Python, только tp_call обновляется, что, вероятно, сделает его несогласованным с функцией vectorcall.Изменено в версии 3.8: До версии 3.8 этот слот назывался
tp_print. В Python 2.x он использовался для вывода в файл. В Python 3.0–3.7 он не использовался.Наследование:
Это поле всегда наследуется. Однако флаг
Py_TPFLAGS_HAVE_VECTORCALLне всегда наследуется. Если это не так, то подкласс не будет использовать vectorcall, за исключением случаев, когдаPyVectorcall_Call()вызывается явно. Это особенно относится к типам кучи (включая подклассы, определенные в Python).
-
getattrfunc PyTypeObject.tp_getattr -
Необязательный указатель на функцию получения атрибута-строки.
Это поле устарело. При его определении оно должно указывать на функцию, которая действует так же, как функция
tp_getattro, но принимает строку C вместо объекта строки Python для указания имени атрибута.Наследование:
Группа:
tp_getattr,tp_getattroЭто поле наследуется подтипами вместе с
tp_getattro: подтип наследует какtp_getattr, так иtp_getattroот своего базового типа, когдаtp_getattrиtp_getattroподтипа обаNULL.
-
setattrfunc PyTypeObject.tp_setattr -
Необязательный указатель на функцию для установки и удаления атрибутов.
Это поле устарело. При его определении оно должно указывать на функцию, которая действует так же, как функция
tp_setattro, но принимает строку C вместо объекта строки Python для указания имени атрибута.Наследование:
Группа:
tp_setattr,tp_setattroЭто поле наследуется подтипами вместе с
tp_setattro: подтип наследует какtp_setattr, так иtp_setattroот своего базового типа, когдаtp_setattrиtp_setattroподтипа обаNULL.
-
PyAsyncMethods *PyTypeObject.tp_as_async -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протоколы awaitable и асинхронного итератора на уровне C. См. Структуры асинхронных объектов для получения подробностей.
Введено в версии 3.5: Ранее известный как
tp_compareиtp_reserved.Наследование:
Поле
tp_as_asyncне наследуется, но содержащиеся поля наследуются индивидуально.
-
reprfunc PyTypeObject.tp_repr -
Необязательный указатель на функцию, которая реализует встроенную функцию
repr().Подпись такая же, как у
PyObject_Repr():PyObject *tp_repr(PyObject *self);
Функция должна возвращать строку или объект Unicode. В идеале эта функция должна возвращать строку, которая, когда передается в
eval(), в подходящей среде возвращает объект с тем же значением. Если это не представляется возможным, она должна возвращать строку, начинающуюся с'<'и заканчивающуюся'>', из которой можно вывести тип и значение объекта.Наследование:
Это поле наследуется подтипами.
По умолчанию:
Если это поле не установлено, возвращается строка вида
<%s object at %p>, где%sзаменяется именем типа, а%p— адрес памяти объекта.
-
PyNumberMethods *PyTypeObject.tp_as_number -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протокол чисел. Эти поля описаны в Структуры численных объектов.
Наследование:
Поле
tp_as_numberне наследуется, но содержащиеся поля наследуются индивидуально.
-
PySequenceMethods *PyTypeObject.tp_as_sequence -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протокол последовательностей. Эти поля описаны в Структуры объектов последовательностей.
Наследование:
Поле
tp_as_sequenceне наследуется, но содержащиеся поля наследуются индивидуально.
-
PyMappingMethods *PyTypeObject.tp_as_mapping -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, которые реализуют протокол отображения. Эти поля описаны в Структуры объектов отображения.
Наследование:
Поле
tp_as_mappingне наследуется, но содержащиеся поля наследуются индивидуально.
-
hashfunc PyTypeObject.tp_hash -
Необязательный указатель на функцию, реализующую встроенную функцию
hash().Подпись такая же, как у
PyObject_Hash():Py_hash_t tp_hash(PyObject *);
Значение
-1не должно возвращаться как нормальное значение возврата; при возникновении ошибки во время вычисления значения хэша функция должна установить исключение и вернуть-1.Если этот параметр не установлен (и
tp_richcompareтакже не установлен), попытка вычисления хэша объекта вызываетTypeError. Это эквивалентно его установке вPyObject_HashNotImplemented().Этот параметр можно явно установить в
PyObject_HashNotImplemented(), чтобы заблокировать наследование метода хэширования от родительского типа. Это интерпретируется как эквивалент__hash__ = Noneна уровне Python, заставляяisinstance(o, collections.Hashable)корректно возвращатьFalse. Обратите внимание, что обратное также верно — установка__hash__ = Noneв классе на уровне Python приведет к тому, что слотtp_hashбудет установлен вPyObject_HashNotImplemented().Наследование:
Группа:
tp_hash,tp_richcompareЭтот параметр наследуется подтипами вместе с
tp_richcompare: подтип наследует обаtp_richcompareиtp_hash, когда у подтипа обаtp_richcompareиtp_hash—NULL.
-
ternaryfunc PyTypeObject.tp_call -
Необязательный указатель на функцию, реализующую вызов объекта. Должен быть
NULLесли объект не вызываемый. Подпись такая же, как уPyObject_Call():PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);
Наследование:
Этот параметр наследуется подтипами.
-
reprfunc PyTypeObject.tp_str -
Необязательный указатель на функцию, реализующую встроенную операцию
str(). (Обратите внимание, чтоstrтеперь является типом, иstr()вызывает конструктор для этого типа. Этот конструктор вызываетPyObject_Str()для выполнения фактической работы, иPyObject_Str()будет вызывать этот обработчик.)Подпись такая же, как у
PyObject_Str():PyObject *tp_str(PyObject *self);
Функция должна вернуть строку или объект Unicode. Это должно быть «дружественное» строковое представление объекта, так как это представление, среди прочего, будет использоваться функцией
print().Наследование:
Этот параметр наследуется подтипами.
По умолчанию:
Если этот параметр не задан, вызывается
PyObject_Repr()для возвращения строкового представления.
-
getattrofunc PyTypeObject.tp_getattro -
Необязательный указатель на функцию получения атрибута.
Подпись такая же, как у
PyObject_GetAttr():PyObject *tp_getattro(PyObject *self, PyObject *attr);
Обычно удобно установить этот параметр в
PyObject_GenericGetAttr(), который реализует стандартный способ поиска атрибутов объекта.Наследование:
Группа:
tp_getattr,tp_getattroЭтот параметр наследуется подтипами вместе с
tp_getattr: подтип наследует какtp_getattr, так иtp_getattroот базового типа, когда у подтипа обаtp_getattrиtp_getattro—NULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericGetAttr().
-
setattrofunc PyTypeObject.tp_setattro -
Необязательный указатель на функцию для установки и удаления атрибутов.
Подпись такая же, как у
PyObject_SetAttr():int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
Кроме того, установка value в
NULLдля удаления атрибута должна поддерживаться. Обычно удобно установить этот параметр вPyObject_GenericSetAttr(), который реализует стандартный способ установки атрибутов объекта.Наследование:
Группа:
tp_setattr,tp_setattroЭтот параметр наследуется подтипами вместе с
tp_setattr: подтип наследует какtp_setattr, так иtp_setattroот базового типа, когда у подтипа обаtp_setattrиtp_setattro—NULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericSetAttr().
-
PyBufferProcs *PyTypeObject.tp_as_buffer -
Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим интерфейс буфера. Эти поля документированы в Структуры объекта буфера.
Наследование:
Параметр
tp_as_bufferне наследуется, но содержащиеся поля наследуются по отдельности.
-
unsigned long PyTypeObject.tp_flags
-
Это поле представляет собой битовую маску различных флагов. Некоторые флаги указывают на варианты семантики в определенных ситуациях; другие используются для обозначения того, что некоторые поля в объекте типа (или в структурах расширений, на которые ссылаются через
tp_as_number,tp_as_sequence,tp_as_mappingиtp_as_buffer), которые исторически не всегда присутствовали, являются допустимыми; если такой битовый флаг сброшен, поля типа, которые он защищает, не должны обращаться и должны рассматриваться как имеющие значение ноль илиNULL.Наследование:
Наследование этого поля сложно. Большинство битов флагов наследуются индивидуально, т. е. если базовый тип имеет установленный битовый флаг, подтип наследует этот битовый флаг. Биты флагов, относящиеся к структурам расширений, строго наследуются, если структура расширения наследуется, т. е. значение базового типа битового флага копируется в подтип вместе с указателем на структуру расширения. Флажок
Py_TPFLAGS_HAVE_GCнаследуется вместе с полямиtp_traverseиtp_clear, т. е. если битовый флагPy_TPFLAGS_HAVE_GCсброшен в подтипе, а поляtp_traverseиtp_clearв подтипе существуют и имеютNULLзначения.Значение по умолчанию:
PyBaseObject_TypeиспользуетPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.Битовые маски:
В настоящее время определены следующие битовые маски; их можно объединить с помощью оператора
|для формирования значения поляtp_flags. МакросPyType_HasFeature()принимает тип и значение флага, tp и f, и проверяет,tp->tp_flags & fне равно нулю.-
Py_TPFLAGS_HEAPTYPE -
Этот бит установлен, когда сам объект типа выделяется в куче, например, типы, созданные динамически с помощью
PyType_FromSpec(). В этом случае полеob_typeего экземпляров считается ссылкой на тип, и объект типа INCREF при создании нового экземпляра и DECREF при уничтожении экземпляра (это не относится к экземплярам подтипов; только тип, на который ссылается ob_type экземпляра, получает INCREF или DECREF).Наследование:
???
-
Py_TPFLAGS_BASETYPE -
Этот бит установлен, когда тип может использоваться в качестве базового типа другого типа. Если этот бит сброшен, тип не может быть подтипом (аналогично классу «final» в Java).
Наследование:
???
-
Py_TPFLAGS_READY -
Этот бит установлен, когда объект типа был полностью инициализирован функцией
PyType_Ready().Наследование:
???
-
Py_TPFLAGS_READYING -
Этот бит установлен во время инициализации объекта типа функцией
PyType_Ready().Наследование:
???
-
Py_TPFLAGS_HAVE_GC -
Этот бит установлен, когда объект поддерживает сборку мусора. Если этот бит установлен, экземпляры должны создаваться с помощью
PyObject_GC_New()и уничтожаться с помощьюPyObject_GC_Del(). Дополнительная информация в разделе Поддержка циклической сборки мусора. Этот бит также подразумевает, что поля, относящиеся к сборке мусора,tp_traverseиtp_clear, присутствуют в объекте типа.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearФлажок
Py_TPFLAGS_HAVE_GCнаследуется вместе с полямиtp_traverseиtp_clear, т. е. если флажокPy_TPFLAGS_HAVE_GCсброшен в подтипе, а поляtp_traverseиtp_clearв подтипе существуют и имеютNULLзначения.
-
Py_TPFLAGS_DEFAULT -
Это битовая маска всех битов, относящихся к существованию определенных полей в объекте типа и его структурах расширений. В настоящее время она включает следующие биты:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.Наследование:
???
-
Py_TPFLAGS_METHOD_DESCRIPTOR -
Этот бит указывает на то, что объекты ведут себя как несвязанные методы.
Если этот флаг установлен для
type(meth), то:-
meth.__get__(obj, cls)(*args, **kwds)(сobjне равным None) должен быть эквивалентенmeth(obj, *args, **kwds). -
meth.__get__(None, cls)(*args, **kwds)должен быть эквивалентенmeth(*args, **kwds).
Этот флаг позволяет оптимизировать типичные вызовы методов, такие как
obj.meth(): он избегает создания временного объекта «связанного метода» дляobj.meth.Введено в версии 3.8.
Наследование:
Этот флаг никогда не наследуется типами кучи. Для типов расширений он наследуется, когда
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_callтакже наследуется. Типы кучи не наследуютPy_TPFLAGS_HAVE_VECTORCALL.Введено в версии 3.9.
-
Py_TPFLAGS_IMMUTABLETYPE -
Этот бит установлен для объектов типа, которые являются неизменяемыми: атрибуты типа не могут быть установлены или удалены.
PyType_Ready()автоматически применяет этот флаг к статическим типам.Наследование:
Этот флаг не наследуется.
Введено в версии 3.10.
-
-
Py_TPFLAGS_DISALLOW_INSTANTIATION -
Запретить создание экземпляров типа: установите
tp_newв NULL и не создавайте ключ__new__в словаре типа.Флаг должен быть установлен до создания типа, а не после. Например, он должен быть установлен до вызова
PyType_Ready()для типа.Флаг автоматически устанавливается для статических типов, если
tp_baseравен NULL или&PyBaseObject_Typeиtp_newравен NULL.Наследование:
Этот флаг не наследуется. Однако подклассы не будут создаваться в экземпляры, если они не предоставят ненулевой
tp_new(что возможно только через API на C).Примечание
Для запрещения прямого создания экземпляров класса, но разрешения создания экземпляров его подклассов (например, для абстрактного базового класса), не используйте этот флаг. Вместо этого заставьте
tp_newсработать только для подклассов.Добавлена в версии 3.10.
-
Py_TPFLAGS_MAPPING -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам отображения, когда используются в качестве объекта в блоке
match. Он автоматически устанавливается при регистрации или наследованииcollections.abc.Mappingи сбрасывается при регистрацииcollections.abc.Sequence.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимно исключают друг друга; одновременная установка обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, которые еще не установили
Py_TPFLAGS_SEQUENCE.См. также
PEP 634 – Спецификация структурного сопоставления
Добавлена в версии 3.10.
-
Py_TPFLAGS_SEQUENCE -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам последовательностей, когда используются в качестве объекта в блоке
match. Он автоматически устанавливается при регистрации или наследованииcollections.abc.Sequenceи сбрасывается при регистрацииcollections.abc.Mapping.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимно исключают друг друга; одновременная установка обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, которые еще не установили
Py_TPFLAGS_MAPPING.См. также
PEP 634 – Спецификация структурного сопоставления
Добавлена в версии 3.10.
-
-
const char *PyTypeObject.tp_doc -
Необязательный указатель на строку C с нулевым завершением, содержащую строку документации для этого объекта типа. Она экспонируется как атрибут
__doc__для типа и экземпляров этого типа.Наследование:
Это поле не наследуется подтипами.
-
traverseproc PyTypeObject.tp_traverse -
Необязательный указатель на функцию обхода для сборщика мусора. Используется только если установлен бит флага
Py_TPFLAGS_HAVE_GC. Подпись функции:int tp_traverse(PyObject *self, visitproc visit, void *arg);
Дополнительную информацию о схеме сборки мусора Python можно найти в разделе Поддержка циклического сборщика мусора.
Указатель
tp_traverseиспользуется сборщиком мусора для обнаружения циклов ссылок. Типичная реализация функцииtp_traverseпросто вызываетPy_VISIT()для каждого члена экземпляра, который является объектом Python, которым экземпляр владеет. Например, эта функцияlocal_traverse()из модуля расширения_thread:static int local_traverse(localobject *self, visitproc visit, void *arg) { Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }Обратите внимание, что
Py_VISIT()вызывается только для тех членов, которые могут участвовать в циклах ссылок. Хотя есть также членself->key, он может быть толькоNULLили строкой Python и поэтому не может быть частью цикла ссылок.С другой стороны, даже если вы знаете, что член никогда не может быть частью цикла, в качестве средства отладки вы можете посетить его, просто чтобы функция модуля
gcget_referents()включила его.Предупреждение
При реализации
tp_traverse, необходимо посетить только те члены, которыми экземпляр владеет (имея сильные ссылки на них). Например, если объект поддерживает слабые ссылки через слотtp_weaklist, указатель, поддерживающий связанный список (на что указывает tp_weaklist), не должен посещаться, так как экземпляр не владеет напрямую слабыми ссылками на элементы в нём (список weakreference предназначен для поддержки механизма слабых ссылок, но экземпляр не имеет сильной ссылки на элементы внутри него, так как они могут быть удалены, даже если экземпляр всё ещё жив).Обратите внимание, что
Py_VISIT()требует, чтобы параметры visit и arg функцииlocal_traverse()имели эти конкретные имена; не называйте их просто как угодно.Экземпляры кучных типов содержат ссылку на свой тип. Поэтому их функция обхода должна либо посетить
Py_TYPE(self), либо делегировать эту задачу, вызвавtp_traverseдругого кучного типа (например, кучного суперкласса). В противном случае объект типа может не быть собран мусором.Изменено в версии 3.9: Ожидается, что кучные типы будут посещать
Py_TYPE(self)вtp_traverse. В более ранних версиях Python из-за ошибки 40217 это может привести к сбою в подклассах.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭто поле наследуется подтипами вместе с
tp_clearи битом флагаPy_TPFLAGS_HAVE_GC: бит флага,tp_traverseиtp_clearнаследуются от базового типа, если все они равны нулю в подтипе.
-
inquiry PyTypeObject.tp_clear -
Необязательный указатель на функцию очистки для сборщика мусора. Используется только если установлен флаг
Py_TPFLAGS_HAVE_GC. Сигнатура:int tp_clear(PyObject *);
Функция
tp_clearиспользуется для разрыва циклических ссылок в циклическом мусоре, обнаруженном сборщиком мусора. В совокупности все функцииtp_clearв системе должны объединяться для разрыва всех циклических ссылок. Это тонкий момент, и в случае сомнений следует предоставить функциюtp_clear. Например, тип кортежей не реализует функциюtp_clear, поскольку можно доказать, что ни один циклический указатель не может быть полностью составлен из кортежей. Поэтому функцииtp_clearдругих типов должны быть достаточны для разрыва любого цикла, содержащего кортеж. Это не очевидно сразу, и редко есть веская причина избегать реализацииtp_clear.Реализации функций
tp_clearдолжны прервать ссылки экземпляра на те из его членов, которые могут быть объектами Python, и установить их указатели на эти члены вNULL, как в следующем примере:static int local_clear(localobject *self) { Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }Следует использовать макрос
Py_CLEAR(), поскольку очистка ссылок – тонкая операция: ссылка на содержащий объект не должна быть освобождена (черезPy_DECREF()) до тех пор, пока указатель на содержащий объект не будет установлен вNULL. Это потому, что освобождение ссылки может привести к тому, что содержащий объект станет мусором, что вызовет цепочку действий по рекуперации, которая может включать вызов произвольного кода Python (из-за финализаторов или обратных вызовов weakref, связанных с содержащим объектом). Если такой код может снова ссылаться на self, важно, чтобы указатель на содержащий объект былNULLв этот момент, чтобы self знал, что содержащий объект больше нельзя использовать. МакросPy_CLEAR()выполняет операции в безопасном порядке.Обратите внимание, что
tp_clearне всегда вызывается перед удалением экземпляра. Например, когда счетчик ссылок достаточно определяет, что объект больше не используется, циклический сборщик мусора не участвует и вызывается непосредственноtp_dealloc.Поскольку цель функций
tp_clear– разрыв циклических ссылок, нет необходимости очищать содержащие объекты, такие как строки Python или целые числа Python, которые не могут участвовать в циклических ссылках. С другой стороны, может быть удобно очистить все содержащие объекты Python и написать функциюtp_deallocтипа, чтобы вызватьtp_clear.Дополнительную информацию о схеме сбора мусора Python можно найти в разделе Поддержка циклического сбора мусора.
Наследование:
Группа:
Py_TPFLAGS_HAVE_GC,tp_traverse,tp_clearЭтот атрибут наследуется подтипами вместе с
tp_traverseи флагомPy_TPFLAGS_HAVE_GC: флаг,tp_traverseиtp_clearнаследуются от базового типа, если все они равны нулю в подтипе.
-
richcmpfunc PyTypeObject.tp_richcompare -
Необязательный указатель на функцию богатого сравнения, сигнатура которой:
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
Первый параметр гарантированно является экземпляром типа, определенного в
PyTypeObject.Функция должна вернуть результат сравнения (обычно
Py_TrueилиPy_False). Если сравнение не определено, она должна вернутьPy_NotImplemented, если произошла другая ошибка, она должна вернутьNULLи установить условие исключения.Следующие константы определены для использования в качестве третьего аргумента для
tp_richcompareи дляPyObject_RichCompare():Константа
Сравнение
Py_LT<Py_LE<=Py_EQ==Py_NE!=Py_GT>Py_GE>=Следующий макрос определен для упрощения написания функций богатого сравнения:
-
Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op) -
Возвращает
Py_TrueилиPy_Falseиз функции в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочиваемы операторами C сравнения (например, это могут быть целые числа C или числа с плавающей точкой). Третий аргумент указывает запрашиваемую операцию, как дляPyObject_RichCompare().Возвращаемое значение – новая сильная ссылка.
В случае ошибки устанавливает исключение и возвращает
NULLиз функции.Введено в версии 3.7.
Наследование:
Группа:
tp_hash,tp_richcompareЭтот атрибут наследуется подтипами вместе с
tp_hash: подтип наследуетtp_richcompareиtp_hash, когдаtp_richcompareиtp_hashподтипа оба равныNULL.По умолчанию:
PyBaseObject_Typeпредоставляет реализациюtp_richcompare, которая может быть унаследована. Однако, если определен толькоtp_hash, не используется даже унаследованная функция, и экземпляры типа не смогут участвовать ни в каких сравнениях. -
-
Py_ssize_t PyTypeObject.tp_weaklistoffset -
Если экземпляры этого типа могут быть слабо ссылаемыми, это поле больше нуля и содержит смещение в структуре экземпляра для начала списка слабых ссылок (игнорируя заголовок GC, если он присутствует); это смещение используется функциями
PyObject_ClearWeakRefs()иPyWeakref_*. Структура экземпляра должна содержать поле типаPyObject*, инициализированное значениемNULL.Не путайте это поле с
tp_weaklist; это начало списка слабых ссылок на сам объект типа.Наследование:
Это поле наследуется подтипами, но см. правила ниже. Подтип может переопределить это смещение; это означает, что подтип использует другое начало списка слабых ссылок, чем базовый тип. Поскольку начало списка всегда находится с помощью
tp_weaklistoffset, это не должно быть проблемой.Когда тип, определённый оператором класса, не имеет объявления
__slots__, и ни один из его базовых типов не является слабо ссылаемым, тип делается слабо ссылаемым путём добавления слота начала списка слабых ссылок в структуру экземпляра и установкой смещения этого слота вtp_weaklistoffset.Когда объявление типа
__slots__содержит слот с именем__weakref__, этот слот становится началом списка слабых ссылок для экземпляров типа, а смещение слота сохраняется вtp_weaklistoffsetтипа.Когда объявление типа
__slots__не содержит слота с именем__weakref__, тип наследуетtp_weaklistoffsetот своего базового типа.
-
getiterfunc PyTypeObject.tp_iter -
Необязательный указатель на функцию, которая возвращает итератор для объекта. Его наличие обычно означает, что экземпляры этого типа являются итерируемыми (хотя последовательности могут быть итерируемыми без этой функции).
Эта функция имеет ту же сигнатуру, что и
PyObject_GetIter():PyObject *tp_iter(PyObject *self);
Наследование:
Это поле наследуется подтипами.
-
iternextfunc PyTypeObject.tp_iternext -
Необязательный указатель на функцию, которая возвращает следующий элемент в итераторе. Сигнатура:
PyObject *tp_iternext(PyObject *self);
Когда итератор исчерпан, он должен вернуть
NULL; исключениеStopIterationможет быть или не быть установлено. При возникновении другой ошибки он также должен вернутьNULL. Его наличие означает, что экземпляры этого типа являются итераторами.Типы итераторов также должны определять функцию
tp_iter, и эта функция должна возвращать сам экземпляр итератора (а не новый экземпляр итератора).Эта функция имеет ту же сигнатуру, что и
PyIter_Next().Наследование:
Это поле наследуется подтипами.
-
struct PyMethodDef *PyTypeObject.tp_methods -
Необязательный указатель на статический
NULL-завершающий массив структурPyMethodDef, объявляющих обычные методы этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель метода.Наследование:
Это поле не наследуется подтипами (методы наследуются по другому механизму).
-
struct PyMemberDef *PyTypeObject.tp_members -
Необязательный указатель на статический
NULL-завершающий массив структурPyMemberDef, объявляющих обычные данные членов (полей или слотов) экземпляров этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель члена.Наследование:
Это поле не наследуется подтипами (члены наследуются по другому механизму).
-
struct PyGetSetDef *PyTypeObject.tp_getset -
Необязательный указатель на статический
NULL-завершающий массив структурPyGetSetDef, объявляющий вычисляемые атрибуты экземпляров этого типа.Для каждой записи в массиве добавляется запись в словарь типа (см.
tp_dictниже), содержащая описатель getset.Наследование:
Это поле не наследуется подтипами (вычисляемые атрибуты наследуются по другому механизму).
-
PyTypeObject *PyTypeObject.tp_base -
Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа путём вызова метатипа.
Примечание
Инициализация слотов подчиняется правилам инициализации глобальных переменных. C99 требует, чтобы инициализаторы были «константами адресов». Указатели на функции, такие как
PyType_GenericNew()с неявным преобразованием в указатель, являются допустимыми константами адресов C99.Однако, унарный оператор ‘&’, применённый к нестатической переменной, такой как
PyBaseObject_Type()не обязан создавать константу адреса. Компиляторы могут поддерживать это (gcc поддерживает), MSVC не поддерживает. Оба компилятора строго соответствуют стандарту в этом конкретном поведении.Следовательно,
tp_baseдолжен быть установлен в функции инициализации расширения модуля.Наследование:
Это поле не наследуется подтипами (очевидно).
Значение по умолчанию:
По умолчанию это поле равно
&PyBaseObject_Type(что для программистов Python известно как типobject).
-
PyObject *PyTypeObject.tp_dict -
Словарь типа хранится здесь функцией
PyType_Ready().Это поле обычно должно быть инициализировано значением
NULLперед вызовом PyType_Ready; оно также может быть инициализировано словарем, содержащим начальные атрибуты для типа. После того, какPyType_Ready()инициализировала тип, дополнительные атрибуты для типа могут быть добавлены в этот словарь только если они не соответствуют перегруженным операциям (например,__add__()).Наследование:
Это поле не наследуется подтипами (хотя атрибуты, определённые здесь, наследуются по другому механизму).
Значение по умолчанию:
Если это поле
NULL,PyType_Ready()присвоит ему новый словарь.Предупреждение
Небезопасно использовать
PyDict_SetItem()наtp_dictили иным образом изменять его с использованием API словарей C.
-
descrgetfunc PyTypeObject.tp_descr_get -
Необязательный указатель на функцию «получения описателя».
Сигнатура функции:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
Наследование:
Это поле наследуется подтипами.
-
descrsetfunc PyTypeObject.tp_descr_set -
Необязательный указатель на функцию для установки и удаления значения описателя.
Сигнатура функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Аргумент value устанавливается в
NULLдля удаления значения.Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t PyTypeObject.tp_dictoffset -
Если экземпляры данного типа имеют словарь, содержащий переменные экземпляра, это поле отлично от нуля и содержит смещение в экземплярах типа словаря переменных экземпляра; это смещение используется
PyObject_GenericGetAttr().Не путайте это поле с
tp_dict; это словарь для атрибутов самого объекта типа.Если значение этого поля больше нуля, оно задаёт смещение от начала структуры экземпляра. Если значение меньше нуля, оно задаёт смещение от конца структуры экземпляра. Отрицательное смещение дороже в использовании и должно использоваться только тогда, когда структура экземпляра содержит часть переменной длины. Это используется, например, для добавления словаря переменных экземпляра к подтипам
strилиtuple. Обратите внимание, что полеtp_basicsizeдолжно учитывать добавленный словарь в конце в этом случае, даже если словарь не включён в базовую структуру объекта. В системе с размером указателя 4 байтаtp_dictoffsetследует установить в-4для указания, что словарь находится в самом конце структуры.Действительное смещение словаря в экземпляре можно вычислить из отрицательного
tp_dictoffsetследующим образом:dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset if dictoffset is not aligned on sizeof(void*): round up to sizeof(void*)где
tp_basicsize,tp_itemsizeиtp_dictoffsetвзяты из объекта типа, аob_sizeвзято из экземпляра. Абсолютное значение берётся, так как целые числа используют знакob_sizeдля хранения знака числа. (Вам никогда не потребуется выполнять этот расчёт самостоятельно; он выполняется за вас_PyObject_GetDictPtr().)Наследование:
Это поле наследуется подтипами, но см. правила ниже. Подтип может переопределить это смещение; это означает, что экземпляры подтипа хранят словарь по другому смещению, чем базовый тип. Поскольку словарь всегда находится через
tp_dictoffset, это не должно вызывать проблем.Когда тип, определённый оператором класса, не имеет объявления
__slots__, и ни один из его базовых типов не имеет словаря переменных экземпляра, в структуру экземпляра добавляется слот словаря, иtp_dictoffsetустанавливается в смещение этого слота.Когда тип, определённый оператором класса, имеет объявление
__slots__, тип наследуетtp_dictoffsetот своего базового типа.(Добавление слота с именем
__dict__к объявлению__slots__не имеет ожидаемого эффекта, это только вызывает путаницу. Возможно, это следует добавить в качестве функции, как и__weakref__.)Значение по умолчанию:
Этот слот не имеет значения по умолчанию. Для статических типов, если поле
NULL, то для экземпляров не создаётся__dict__.
-
initproc PyTypeObject.tp_init -
Необязательный указатель на функцию инициализации экземпляра.
Эта функция соответствует методу
__init__()классов. Как и__init__(), возможно создать экземпляр без вызова__init__(), и можно повторно инициализировать экземпляр, вызвав его метод__init__()снова.Подпись функции:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
Аргумент self — это экземпляр, подлежащий инициализации; аргументы args и kwds представляют позиционные и именованные аргументы вызова
__init__().Функция
tp_init, если неNULL, вызывается при создании экземпляра стандартным способом путём вызова его типа после того, как функцияtp_newтипа вернула экземпляр типа. Если функцияtp_newвозвращает экземпляр другого типа, который не является подтипом исходного типа, никакая функцияtp_initне вызывается; еслиtp_newвозвращает экземпляр подтипа исходного типа, вызываетсяtp_initподтипа.Возвращает
0при успехе,-1и устанавливает исключение при ошибке.Наследование:
Это поле наследуется подтипами.
Значение по умолчанию:
Для статических типов это поле не имеет значения по умолчанию.
-
allocfunc PyTypeObject.tp_alloc -
Необязательный указатель на функцию выделения памяти экземпляра.
Подпись функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса).
Значение по умолчанию:
Для динамических подтипов это поле всегда устанавливается в
PyType_GenericAlloc(), чтобы принудительно использовать стандартную стратегию выделения памяти.Для статических подтипов
PyBaseObject_TypeиспользуетPyType_GenericAlloc(). Это рекомендуемое значение для всех статически определённых типов.
-
newfunc PyTypeObject.tp_new -
Необязательный указатель на функцию создания экземпляра.
Подпись функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент subtype — это тип создаваемого объекта; аргументы args и kwds представляют позиционные и именованные аргументы вызова типа. Обратите внимание, что subtype не обязательно должен быть равен типу, чья функция
tp_newвызывается; он может быть подтипом этого типа (но не несвязанным типом).Функция
tp_newдолжна вызватьsubtype->tp_alloc(subtype, nitems)для выделения памяти под объект, а затем выполнить только абсолютно необходимую дополнительную инициализацию. Инициализация, которую можно безопасно пропустить или повторить, должна быть помещена в обработчикtp_init. Хорошее эмпирическое правило состоит в том, что для неизменяемых типов вся инициализация должна происходить вtp_new, а для изменяемых типов большая часть инициализации должна откладываться наtp_init.Установите флаг
Py_TPFLAGS_DISALLOW_INSTANTIATIONдля запрета создания экземпляров типа в Python.Наследование:
Это поле наследуется подтипами, за исключением статических типов, чьё
tp_baseравноNULLили&PyBaseObject_Type.Значение по умолчанию:
Для статических типов это поле не имеет значения по умолчанию. Это означает, что если слот определён как
NULL, тип не может вызываться для создания новых экземпляров; предположительно, существует какой-то другой способ создания экземпляров, например, функция-фабрика.
-
freefunc PyTypeObject.tp_free -
Необязательный указатель на функцию освобождения памяти экземпляра. Её подпись:
void tp_free(void *self);
Инициализатор, совместимый с этой подписью, —
PyObject_Free().Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса).
Значение по умолчанию:
В динамических подтипах это поле устанавливается в деаллокатор, подходящий для
PyType_GenericAlloc()и значения бита флагаPy_TPFLAGS_HAVE_GC.Для статических подтипов
PyBaseObject_Typeиспользует PyObject_Del.
-
inquiry PyTypeObject.tp_is_gc -
Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщику мусора нужно знать, является ли конкретный объект собираемым. Обычно достаточно посмотреть на поле
tp_flagsтипа объекта и проверить бит флагаPy_TPFLAGS_HAVE_GC. Однако некоторые типы имеют смесь статически и динамически выделенных экземпляров, причём статически выделенные экземпляры не собираются. Такие типы должны определять эту функцию; она должна возвращать1для собираемого экземпляра и0для несобираемого экземпляра. Сигнатура:int tp_is_gc(PyObject *self);
(Единственный пример – это сами типы. Меттатип,
PyType_Type, определяет эту функцию, чтобы различать статически и динамически выделенные типы.)Наследование:
Это поле наследуется подтипами.
Значение по умолчанию:
У этого слота нет значения по умолчанию. Если это поле
NULL, используетсяPy_TPFLAGS_HAVE_GCв качестве функционального эквивалента.
-
PyObject *PyTypeObject.tp_bases -
Кортеж типов-баз.
Это поле должно быть установлено в
NULLи обрабатываться как неизменяемое. Python заполнит его, когда тип будетinitialized.Для динамически созданных классов вместо аргумента bases функции
PyType_FromSpecWithBases()можно использоватьPy_tp_basesslot. Предпочтительнее использовать аргумент в таком формате.Предупреждение
Многократное наследование не работает хорошо для статически определённых типов. Если вы установите
tp_basesв кортеж, Python не выведет ошибку, но некоторые слоты будут унаследованы только от первого базового типа.Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_mro -
Кортеж, содержащий расширенный набор типов-баз, начиная с самого типа и заканчивая
object, в порядке разрешения методов.Это поле должно быть установлено в
NULLи обрабатываться как неизменяемое. Python заполнит его, когда тип будетinitialized.Наследование:
Это поле не наследуется; оно вычисляется заново функцией
PyType_Ready().
-
PyObject *PyTypeObject.tp_cache -
Не используется. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_subclasses -
Список слабых ссылок на подклассы. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_weaklist -
Голова списка слабых ссылок для слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_del -
Это поле устарело. Используйте
tp_finalizeвместо него.
-
unsigned int PyTypeObject.tp_version_tag -
Используется для индексирования в кэше методов. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_finalize -
Необязательный указатель на функцию завершения экземпляра. Её сигнатура:
void tp_finalize(PyObject *self);
Если
tp_finalizeустановлена, интерпретатор вызывает её один раз при завершении экземпляра. Она вызывается либо сборщиком мусора (если экземпляр входит в изолированный цикл ссылок), либо непосредственно перед удалением объекта. В любом случае гарантируется, что она будет вызвана до попытки разорвать циклы ссылок, обеспечивая, что она найдёт объект в нормальном состоянии.tp_finalizeне должна изменять текущее состояние исключения; поэтому рекомендуемый способ написания нетривиального завершающего метода:static void local_finalize(PyObject *self) { PyObject *error_type, *error_value, *error_traceback; /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); /* ... */ /* Restore the saved exception. */ PyErr_Restore(error_type, error_value, error_traceback); }Также обратите внимание, что в Python со сборкой мусора
tp_deallocможет вызываться из любого потока Python, а не только из потока, который создал объект (если объект попадает в цикл ссылок с отсчётом ссылок, этот цикл может быть собран сборкой мусора в любом потоке). Это не проблема для вызовов API Python, так как поток, в котором вызывается tp_dealloc, будет владеть глобальной блокировкой интерпретатора (GIL). Однако, если объект, который уничтожается, в свою очередь уничтожает объекты из какой-либо другой библиотеки C или C++, следует позаботиться о том, чтобы уничтожение этих объектов в потоке, который вызвал tp_dealloc, не нарушало никаких предположений библиотеки.Наследование:
Это поле наследуется подтипами.
Введено в версии 3.4.
Изменено в версии 3.8: До версии 3.8 для использования этого поля необходимо было установить бит флага
Py_TPFLAGS_HAVE_FINALIZE. Это больше не требуется.См. также
“Безопасное завершение объектов” (PEP 442)
-
vectorcallfunc PyTypeObject.tp_vectorcall -
Функция vectorcall для использования при вызовах этого объекта типа. Другими словами, она используется для реализации vectorcall для
type.__call__. Еслиtp_vectorcallравняетсяNULL, используется реализация вызова по умолчанию с использованием__new__и__init__.Наследование:
Это поле никогда не наследуется.
Введено в версии 3.9: (поле существует с 3.8, но используется только с 3.9)
Статические типы
Традиционно, типы, определённые в коде C, являются статическими, то есть структура PyTypeObject статического типа определяется непосредственно в коде и инициализируется с помощью PyType_Ready().
Это приводит к типам, которые ограничены по сравнению с типами, определёнными в Python:
- Статические типы ограничены одним базовым типом, то есть они не могут использовать множественное наследование.
- Объекты статических типов (но не обязательно их экземпляры) являются неизменяемыми. Невозможно добавить или изменить атрибуты объекта типа из Python.
- Объекты статических типов совместно используются между подинтерпретаторами, поэтому они не должны содержать состояние, зависящее от подинтерпретатора.
Кроме того, поскольку PyTypeObject является лишь частью Ограниченного API как непрозрачная структура, любые модули расширений, использующие статические типы, должны быть скомпилированы для конкретной младшей версии Python.
Типы кучи
Альтернатива статическим типам – это типы, выделенные в куче, или кратко типы кучи, которые тесно соответствуют классам, созданным в Python с помощью оператора class. Типы кучи имеют установленный флаг Py_TPFLAGS_HEAPTYPE.
Это делается путём заполнения структуры PyType_Spec и вызова PyType_FromSpec(), PyType_FromSpecWithBases() или PyType_FromModuleAndSpec().
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/c-api/typeobj.html