Структуры объектов типов
Возможно, одна из важнейших структур системы объектов Python — это структура, определяющая новый тип: структура PyTypeObject. Объектами типов можно управлять с помощью любой из функций PyObject_* или PyType_*, однако они не предлагают ничего особенно интересного для большинства приложений Python. Эти объекты лежат в основе поведения объектов, поэтому они очень важны для самого интерпретатора и для любого модуля расширения, реализующего новые типы.
Объекты типов довольно велики по сравнению с большинством стандартных типов. Их размер объясняется тем, что каждый объект типа хранит большое количество значений, в основном указателей на функции C, каждая из которых реализует небольшую часть функциональности типа. В этом разделе подробно рассматриваются поля объекта типа. Поля описаны в том порядке, в котором они расположены в структуре.
Помимо следующей краткой справки, раздел Примеры позволяет быстро понять значение и использование PyTypeObject.
Краткая справка
«Слоты tp»
Слот PyTypeObject [1] | специальные методы/атрибуты | Сведения [2] | ||||
|---|---|---|---|---|---|---|
O | T | D | I | |||
<R> | const char * | __name__ | X | X | ||
X | X | X | ||||
X | X | |||||
X | X | X | ||||
X | X | |||||
__getattribute__, __getattr__ | G | |||||
__setattr__, __delattr__ | G | |||||
% | ||||||
__repr__ | X | X | X | |||
% | ||||||
% | ||||||
% | ||||||
__hash__ | X | G | ||||
__call__ | X | X | ||||
__str__ | X | X | ||||
__getattribute__, __getattr__ | X | X | G | |||
__setattr__, __delattr__ | X | X | G | |||
% | ||||||
unsigned long | X | X | ? | |||
const char * | __doc__ | X | X | |||
X | G | |||||
X | G | |||||
__lt__, __le__, __eq__, __ne__, __gt__, __ge__ | X | G | ||||
X | ? | |||||
__iter__ | X | |||||
__next__ | X | |||||
| X | X | ||||
| X | |||||
| X | X | ||||
__base__ | X | |||||
| __dict__ | ? | ||||
__get__ | X | |||||
__set__, __delete__ | X | |||||
X | ? | |||||
__init__ | X | X | X | |||
X | ? | ? | ||||
__new__ | X | X | ? | ? | ||
X | X | ? | ? | |||
X | X | |||||
< |
| __bases__ | ~ | |||
< |
| __mro__ | ~ | |||
[ |
| |||||
void * | __subclasses__ | |||||
| ||||||
( | ||||||
unsigned int | ||||||
__del__ | X | |||||
unsigned char | ||||||
подслоты
Слот | специальные методы | |
|---|---|---|
__await__ | ||
__aiter__ | ||
__anext__ | ||
__add__ __radd__ | ||
__iadd__ | ||
__sub__ __rsub__ | ||
__isub__ | ||
__mul__ __rmul__ | ||
__imul__ | ||
__mod__ __rmod__ | ||
__imod__ | ||
__divmod__ __rdivmod__ | ||
__pow__ __rpow__ | ||
__ipow__ | ||
__neg__ | ||
__pos__ | ||
__abs__ | ||
__bool__ | ||
__invert__ | ||
__lshift__ __rlshift__ | ||
__ilshift__ | ||
__rshift__ __rrshift__ | ||
__irshift__ | ||
__and__ __rand__ | ||
__iand__ | ||
__xor__ __rxor__ | ||
__ixor__ | ||
__or__ __ror__ | ||
__ior__ | ||
__int__ | ||
void * | ||
__float__ | ||
__floordiv__ | ||
__ifloordiv__ | ||
__truediv__ | ||
__itruediv__ | ||
__index__ | ||
__matmul__ __rmatmul__ | ||
__imatmul__ | ||
__len__ | ||
__getitem__ | ||
__setitem__, __delitem__ | ||
__len__ | ||
__add__ | ||
__mul__ | ||
__getitem__ | ||
__setitem__ __delitem__ | ||
__contains__ | ||
__iadd__ | ||
__imul__ | ||
__buffer__ | ||
__release_buffer__ | ||
определения типов слотов
определение типа | Типы параметров | Тип возвращаемого значения |
|---|---|---|
| ||
| void | |
void * | void | |
int | ||
| ||
int | ||
|
| |
| ||
int | ||
| ||
int | ||
| ||
int | ||
| Py_hash_t | |
| ||
|
| |
|
| |
| ||
int | ||
void | ||
| int | |
| ||
| ||
| ||
| ||
int | ||
int | ||
int |
Подробнее см. ниже в разделе Определения типов слотов.
Определение PyTypeObject
Определение структуры PyTypeObject можно найти в Include/cpython/object.h. Для удобства здесь повторено определение, приведённое там:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
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;
/* bitset of which type-watchers care about this type */
unsigned char tp_watched;
} PyTypeObject;
Слоты PyObject
Структура объекта типа расширяет структуру PyVarObject. Поле ob_size используется для динамических типов (создаваемых с помощью type_new(), обычно вызываемого из инструкции объявления класса). Обратите внимание, что PyType_Type (метатип) инициализирует tp_itemsize, а это означает, что его экземпляры (то есть объекты типов) должны иметь поле ob_size.
-
Py_ssize_t PyObject.ob_refcnt -
Часть стабильного ABI.
Это счётчик ссылок объекта типа, инициализируемый значением
1макросомPyObject_HEAD_INIT. Обратите внимание: для статически размещённых объектов типов экземпляры типа (объекты, у которых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()не изменяет это поле, если оно не равно нулю.Наследование:
Это поле наследуется подклассами.
Слоты PyVarObject
-
Py_ssize_t PyVarObject.ob_size -
Часть стабильного ABI.
Для статически размещённых объектов типов это поле следует инициализировать нулём. Для динамически размещённых объектов типов это поле имеет специальное внутреннее значение.
К этому полю следует обращаться с помощью макросов
Py_SIZE()иPy_SET_SIZE().Наследование:
Это поле не наследуется подклассами.
Слоты PyTypeObject
Для каждого слота есть раздел с описанием наследования. Если PyType_Ready() может установить значение, когда поле установлено в NULL, то также будет раздел «По умолчанию». (Обратите внимание, что многие поля, заданные для PyBaseObject_Type и PyType_Type, фактически служат значениями по умолчанию.)
-
const char *PyTypeObject.tp_name -
Указатель на строку, завершающуюся нулевым байтом и содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, затем точку, а затем имя типа; для встроенных типов в ней должно быть только имя типа. Если модуль является подмодулем пакета, полное имя пакета входит в полное имя модуля. Например, у типа с именем
T, определённого в модулеMподпакетаQпакетаP, инициализаторtp_nameдолжен иметь значение"P.Q.M.T".Для динамически выделяемых объектов типа здесь должно быть только имя типа, а имя модуля должно быть явно сохранено в словаре типа в качестве значения для ключа
'__module__'.Для статически выделяемых объектов типа поле tp_name должно содержать точку. Всё до последней точки становится доступно как атрибут
__module__, а всё после последней точки — как атрибут__name__.Если точка отсутствует, всё поле
tp_nameстановится доступно как атрибут__name__, а атрибут__module__не определён (если только он явно не задан в словаре, как описано выше). Это означает, что ваш тип невозможно будет сериализовать с помощью pickle. Кроме того, он не будет включён в документацию модуля, созданную с помощью pydoc.Это поле не должно быть
NULL. Это единственное обязательное поле вPyTypeObject()(помимо потенциально обязательногоtp_itemsize).Наследование:
Это поле не наследуется подклассами.
-
Py_ssize_t PyTypeObject.tp_basicsize -
Py_ssize_t PyTypeObject.tp_itemsize -
Эти поля позволяют вычислить размер экземпляров типа в байтах.
Существует два вида типов: у типов с экземплярами фиксированной длины поле
tp_itemsizeравно нулю, а у типов с экземплярами переменной длины полеtp_itemsizeне равно нулю. Все экземпляры типа с фиксированной длиной имеют одинаковый размер, указанный вtp_basicsize. (Исключения из этого правила можно создавать с помощьюPyUnstable_Object_GC_NewWithExtraData().)Экземпляры типа с переменной длиной должны иметь поле
ob_size, а размер экземпляра равенtp_basicsizeплюс N, умноженное наtp_itemsize, где N — «длина» объекта.Функции наподобие
PyObject_NewVar()принимают значение N в качестве аргумента и сохраняют его в поле экземпляраob_size. Обратите внимание, что позднее полеob_sizeможет использоваться для других целей. Например, экземплярыintиспользуют битыob_sizeспособом, определяемым реализацией; для доступа к базовому хранилищу и его размеру следует использоватьPyLong_Export().Примечание
Для доступа к полю
ob_sizeследует использовать макросыPy_SIZE()иPy_SET_SIZE().Кроме того, наличие поля
ob_sizeв структуре экземпляра не означает, что структура экземпляра имеет переменную длину. Например, типlistимеет экземпляры фиксированной длины, хотя в этих экземплярах есть полеob_size. (Как и в случае сint, не обращайтесь напрямую кob_sizeсписков. Вместо этого вызовитеPyList_Size().)В
tp_basicsizeвходит размер, необходимый для данных типа из егоtp_base, а также любые дополнительные данные, необходимые каждому экземпляру.Правильно задавать
tp_basicsizeс помощью оператораsizeofдля структуры, используемой для объявления структуры экземпляра. Эта структура должна содержать структуру, используемую для объявления базового типа. Иными словами,tp_basicsizeдолжно быть больше или равноtp_basicsizeбазового типа.Поскольку каждый тип является подклассом
object, эта структура должна содержатьPyObjectилиPyVarObject(в зависимости от того, нужно ли включитьob_size). Обычно для этого используются макросыPyObject_HEADилиPyObject_VAR_HEADсоответственно.Базовый размер не включает размер заголовка GC, так как этот заголовок не является частью
PyObject_HEAD.Если структура, используемая для объявления базового типа, неизвестна, см.
PyType_Spec.basicsizeиPyType_FromMetaclass().Примечания о выравнивании:
-
tp_basicsizeдолжно быть кратно_Alignof(PyObject). При использованииsizeofдляstruct, содержащегоPyObject_HEAD, как и рекомендуется, компилятор обеспечивает это условие. Если вы не используете Cstructили используете расширения компилятора, например__attribute__((packed)), обеспечить это должны вы сами. - Если для элементов переменной части требуется определённое выравнивание,
tp_basicsizeиtp_itemsizeдолжны быть кратны этому выравниванию. Например, если переменная часть типа хранитdouble, вы должны обеспечить, чтобы оба поля были кратны_Alignof(double).
Наследование:
Подклассы наследуют эти поля по отдельности. (То есть, если поле равно нулю,
PyType_Ready()скопирует значение из базового типа, указывая, что экземплярам не требуется дополнительное хранилище.)Если значение
tp_itemsizeбазового типа не равно нулю, обычно небезопасно задавать дляtp_itemsizeподкласса другое ненулевое значение (хотя это зависит от реализации базового типа). -
-
destructor PyTypeObject.tp_dealloc -
Указатель на функцию-деструктор экземпляра. Эта функция должна быть определена, если только тип не гарантирует, что его экземпляры никогда не будут освобождены (как в случае с синглтонами
NoneиEllipsis). Сигнатура функции:void tp_dealloc(PyObject *self);
Функция-деструктор вызывается макросами
Py_DECREF()иPy_XDECREF(), когда новое значение счётчика ссылок становится равным нулю. В этот момент экземпляр ещё существует, но ссылок на него уже нет. Функция-деструктор должна освободить все ссылки, принадлежащие экземпляру, освободить все буферы памяти, принадлежащие экземпляру (используя функцию освобождения, соответствующую функции выделения памяти для буфера), и вызвать функциюtp_freeэтого типа. Если тип нельзя расширять (то есть у него не установлен бит флагаPy_TPFLAGS_BASETYPE), вместо вызоваtp_freeдопустимо напрямую вызвать функцию освобождения объекта. Следует использовать ту функцию освобождения объекта, которая применялась при выделении памяти для экземпляра; обычно этоPyObject_Del(), если экземпляр был выделен с помощьюPyObject_NewилиPyObject_NewVar, либо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); }Предупреждение
В Python со сборщиком мусора функция
tp_deallocможет быть вызвана из любого потока Python, а не только из потока, создавшего объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Для вызовов Python API это не проблема, поскольку поток, в котором вызываетсяtp_dealloc, будет владеть глобальной блокировкой интерпретатора (GIL). Однако, если при уничтожении объекта уничтожаются объекты из другой библиотеки на C или C++, следует убедиться, что уничтожение этих объектов в потоке, вызвавшемtp_dealloc, не нарушит никаких предположений библиотеки.Наследование:
Это поле наследуется подклассами.
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset -
Необязательное смещение до функции для каждого экземпляра, которая реализует вызов объекта с помощью протокола vectorcall — более эффективной альтернативы простому
tp_call.Это поле используется только в том случае, если установлен флаг
Py_TPFLAGS_HAVE_VECTORCALL. В этом случае здесь должно быть положительное целое число, задающее смещение указателяvectorcallfuncв экземпляре.Указатель vectorcallfunc может быть равен
NULL. В этом случае экземпляр ведёт себя так, как если бы флагPy_TPFLAGS_HAVE_VECTORCALLне был установлен: вызов экземпляра используетtp_call.Любой класс, задающий
Py_TPFLAGS_HAVE_VECTORCALL, должен также задаватьtp_callи обеспечивать соответствие его поведения функции vectorcallfunc. Для этого можно задать для tp_call значениеPyVectorcall_Call().Изменено в версии 3.8: До версии 3.8 этот слот назывался
tp_print. В Python 2.x он использовался для вывода в файл. В Python с версии 3.0 по 3.7 он не использовался.Изменено в версии 3.12: До версии 3.12 не рекомендовалось реализовывать протокол vectorcall для изменяемых типов в куче. Когда пользователь задаёт
__call__в коде Python, обновляется только tp_call, из-за чего его поведение, вероятно, становится несогласованным с функцией vectorcall. Начиная с версии 3.12 задание__call__отключает оптимизацию vectorcall, сбрасывая флагPy_TPFLAGS_HAVE_VECTORCALL.Наследование:
Это поле наследуется всегда. Однако флаг
Py_TPFLAGS_HAVE_VECTORCALLнаследуется не всегда. Если он не установлен, подкласс не будет использовать vectorcall, кроме случаев, когда явно вызываетсяPyVectorcall_Call().
-
getattrfunc PyTypeObject.tp_getattr -
Необязательный указатель на функцию получения атрибута по строковому имени.
Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_getattro, но принимает строку C вместо строкового объекта Python в качестве имени атрибута.Наследование:
Группа:
tp_getattr,tp_getattroЭто поле наследуется подклассами вместе с
tp_getattro: подкласс наследует иtp_getattr, иtp_getattroбазового типа, если поляtp_getattrиtp_getattroподкласса равныNULL.
-
setattrfunc PyTypeObject.tp_setattr -
Необязательный указатель на функцию установки и удаления атрибутов.
Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_setattro, но принимает строку C вместо строкового объекта Python в качестве имени атрибута.Наследование:
Группа:
tp_setattr,tp_setattroЭто поле наследуется подклассами вместе с
tp_setattro: подкласс наследует иtp_setattr, иtp_setattroбазового типа, если поляtp_setattrиtp_setattroподкласса равныNULL.
-
PyAsyncMethods *PyTypeObject.tp_as_async -
Указатель на дополнительную структуру с полями, имеющими отношение только к объектам, которые на уровне C реализуют протоколы ожидаемых объектов и асинхронных итераторов. Подробности см. в разделе Структуры асинхронных объектов.
Добавлено в версии 3.5: Ранее называлось
tp_compareиtp_reserved.Наследование:
Поле
tp_as_asyncне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
reprfunc PyTypeObject.tp_repr -
Необязательный указатель на функцию, реализующую встроенную функцию
repr().Сигнатура совпадает с сигнатурой
PyObject_Repr():PyObject *tp_repr(PyObject *self);
Функция должна возвращать строку или объект 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(), чтобы запретить наследование метода хеширования от родительского типа. На уровне Python это интерпретируется как эквивалент__hash__ = None, благодаря чемуisinstance(o, collections.Hashable)правильно возвращаетFalse. Верно и обратное: задание__hash__ = Noneдля класса на уровне Python приводит к тому, что слотуtp_hashприсваивается значениеPyObject_HashNotImplemented().Наследование:
Группа:
tp_hash,tp_richcompareЭто поле наследуется подклассами вместе с
tp_richcompare: подкласс наследует оба поля —tp_richcompareиtp_hash, — если поляtp_richcompareиtp_hashподкласса равныNULL.По умолчанию:
PyBaseObject_TypeиспользуетPyObject_GenericHash().
-
ternaryfunc PyTypeObject.tp_call -
Необязательный указатель на функцию, реализующую вызов объекта. Если объект не вызываемый, здесь должно быть
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. .. XXX действительно ли большинство битов флагов наследуются по отдельности?По умолчанию:
PyBaseObject_TypeиспользуетPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE.Битовые маски:
В настоящее время определены следующие битовые маски; их можно объединять с помощью оператора
|, чтобы сформировать значение поляtp_flags. МакросPyType_HasFeature()принимает тип и значение флагов — tp и f — и проверяет, не равно лиtp->tp_flags & fнулю.-
Py_TPFLAGS_HEAPTYPE -
Этот бит устанавливается, когда сам объект типа размещён в куче, например для типов, созданных динамически с помощью
PyType_FromSpec(). В этом случае полеob_typeего экземпляров считается ссылкой на тип, а при создании нового экземпляра для объекта типа выполняется INCREF, а при уничтожении экземпляра — DECREF (это не относится к экземплярам подтипов; INCREF или DECREF выполняется только для типа, на который ссылается ob_type экземпляра). Типы в куче также должны поддерживать сборку мусора, поскольку они могут образовать цикл ссылок со своим объектом модуля.Наследование:
???
-
Py_TPFLAGS_BASETYPE -
Этот бит устанавливается, если тип может использоваться как базовый тип другого типа. Если этот бит сброшен, от типа нельзя образовывать подтипы (аналогично классу «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.
Наследование:
Этот флаг никогда не наследуется типами, у которых не установлен флаг
Py_TPFLAGS_IMMUTABLETYPE. Для типов расширений он наследуется всякий раз, когда наследуетсяtp_descr_get. -
-
Py_TPFLAGS_MANAGED_DICT -
Этот бит указывает, что у экземпляров класса есть атрибут
__dict__, а память для словаря управляется виртуальной машиной.Если установлен этот флаг, также следует установить
Py_TPFLAGS_HAVE_GC.Функция обхода ссылок типа должна вызывать
PyObject_VisitManagedDict(), а функция очистки —PyObject_ClearManagedDict().Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется, если в суперклассе не задано поле
tp_dictoffset.
-
Py_TPFLAGS_MANAGED_WEAKREF -
Этот бит указывает, что на экземпляры класса должны допускаться слабые ссылки.
Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется, если в суперклассе не задано поле
tp_weaklistoffset.
-
Py_TPFLAGS_ITEMS_AT_END -
Используется только с типами переменного размера, то есть с типами, у которых
tp_itemsizeне равен нулю.Указывает, что область переменного размера экземпляра этого типа находится в конце области памяти экземпляра со смещением
Py_TYPE(obj)->tp_basicsize(которое может различаться у разных подклассов).Устанавливая этот флаг, убедитесь, что все суперклассы либо используют такое расположение памяти, либо не имеют переменного размера. Python это не проверяет.
Добавлено в версии 3.12.
Наследование:
Этот флаг наследуется.
-
Py_TPFLAGS_LONG_SUBCLASS
-
Py_TPFLAGS_LIST_SUBCLASS
-
Py_TPFLAGS_TUPLE_SUBCLASS
-
Py_TPFLAGS_BYTES_SUBCLASS
-
Py_TPFLAGS_UNICODE_SUBCLASS
-
Py_TPFLAGS_DICT_SUBCLASS
-
Py_TPFLAGS_BASE_EXC_SUBCLASS
-
Py_TPFLAGS_TYPE_SUBCLASS -
Эти флаги используются такими функциями, как
PyLong_Check(), чтобы быстро определить, является ли тип подклассом встроенного типа; такие специализированные проверки выполняются быстрее, чем общая проверка, например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.Добавлено в версии 3.9.
Изменено в версии 3.12: Теперь этот флаг снимается с класса, если метод
__call__()класса переназначается.Теперь этот флаг может наследоваться изменяемыми классами.
-
Py_TPFLAGS_IMMUTABLETYPE -
Этот бит устанавливается для неизменяемых объектов типа: атрибуты типа нельзя устанавливать или удалять.
PyType_Ready()автоматически устанавливает этот флаг для статических типов.Наследование:
Этот флаг не наследуется.
Добавлено в версии 3.10.
-
Py_TPFLAGS_DISALLOW_INSTANTIATION -
Запрещает создавать экземпляры типа: установите для
tp_newзначение NULL и не создавайте ключ__new__в словаре типа.Флаг необходимо установить до создания типа, а не после. Например, он должен быть установлен до вызова для типа функции
PyType_Ready().Флаг автоматически устанавливается для статических типов, если
tp_baseимеет значение NULL или&PyBaseObject_Type, аtp_newимеет значение NULL.Наследование:
Этот флаг не наследуется. Однако экземпляры подклассов создавать нельзя, если только они не предоставляют ненулевой
tp_new(это возможно только через C API).Примечание
Чтобы запретить непосредственное создание экземпляров класса, но разрешить создание экземпляров его подклассов (например, для абстрактного базового класса), не используйте этот флаг. Вместо этого сделайте так, чтобы
tp_newуспешно выполнялась только для подклассов.Добавлено в версии 3.10.
-
Py_TPFLAGS_MAPPING -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам отображений, когда используются в качестве проверяемого объекта в блоке
match. Он устанавливается автоматически при регистрации или создании подклассаcollections.abc.Mappingи сбрасывается при регистрацииcollections.abc.Sequence.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимоисключающие; одновременное включение обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, у которых ещё не установлен
Py_TPFLAGS_SEQUENCE.См. также
PEP 634 — Структурное сопоставление с образцом: спецификация
Добавлено в версии 3.10.
-
Py_TPFLAGS_SEQUENCE -
Этот бит указывает, что экземпляры класса могут соответствовать шаблонам последовательностей, когда используются в качестве проверяемого объекта в блоке
match. Он устанавливается автоматически при регистрации или создании подклассаcollections.abc.Sequenceи сбрасывается при регистрацииcollections.abc.Mapping.Примечание
Py_TPFLAGS_MAPPINGиPy_TPFLAGS_SEQUENCEвзаимоисключающие; одновременное включение обоих флагов является ошибкой.Наследование:
Этот флаг наследуется типами, у которых ещё не установлен
Py_TPFLAGS_MAPPING.См. также
PEP 634 — Структурное сопоставление с образцом: спецификация
Добавлено в версии 3.10.
-
Py_TPFLAGS_VALID_VERSION_TAG -
Внутренний флаг. Не устанавливайте и не сбрасывайте его. Чтобы сообщить об изменении класса, вызовите
PyType_Modified()Предупреждение
Этот флаг присутствует в заголовочных файлах, но не используется. Он будет удалён в будущей версии CPython
-
-
const char *PyTypeObject.tp_doc -
Необязательный указатель на завершающуюся NUL C-строку с docstring этого объекта типа. Она доступна как атрибут
__doc__типа и его экземпляров.Наследование:
Это поле не наследуется подтипами.
-
traverseproc PyTypeObject.tp_traverse -
Необязательный указатель на функцию обхода для сборщика мусора. Используется только в том случае, если установлен бит флага
Py_TPFLAGS_HAVE_GC. Сигнатура:int tp_traverse(PyObject *self, visitproc visit, void *arg);
Дополнительные сведения о схеме сборки мусора Python см. в разделе Поддержка циклической сборки мусора.
Указатель
tp_traverseиспользуется сборщиком мусора для обнаружения циклов ссылок. Типичная реализация функцииtp_traverseпросто вызываетPy_VISIT()для каждого члена экземпляра, который является объектом Python и принадлежит этому экземпляру. Например, вот функцияlocal_traverse()из модуля расширения_thread:static int local_traverse(localobject *self, visitproc visit, void *arg) { Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }Обратите внимание, что
Py_VISIT()вызывается только для тех членов, которые могут участвовать в циклах ссылок. Хотя существует также членself->key, он может быть толькоNULLили строкой Python и поэтому не может входить в цикл ссылок.С другой стороны, даже если вы знаете, что член никогда не может входить в цикл, для отладки его можно всё же посещать, чтобы функция
get_referents()модуляgcвключала его в результат.Типы в куче (
Py_TPFLAGS_HEAPTYPE) должны посещать свой тип следующим образом:Py_VISIT(Py_TYPE(self));
Это требуется только начиная с Python 3.9. Для поддержки Python 3.8 и более ранних версий эту строку необходимо поместить в условный блок:
#if PY_VERSION_HEX >= 0x03090000 Py_VISIT(Py_TYPE(self)); #endifЕсли в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, функция обхода должна вызыватьPyObject_VisitManagedDict()следующим образом:PyObject_VisitManagedDict((PyObject*)self, visit, arg);
Предупреждение
При реализации
tp_traverseнеобходимо посещать только те члены, которыми экземпляр владеет (то есть имеет на них сильные ссылки). Например, если объект поддерживает слабые ссылки через слотtp_weaklist, указатель, поддерживающий связанный список (на который указывает tp_weaklist), не следует посещать, поскольку экземпляр не владеет напрямую слабыми ссылками на себя (список слабых ссылок нужен для работы механизма слабых ссылок, но экземпляр не имеет сильных ссылок на содержащиеся в нём элементы, поскольку их можно удалить, даже если экземпляр всё ещё существует).Обратите внимание, что для работы
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_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, функция обхода должна вызыватьPyObject_ClearManagedDict()следующим образом:PyObject_ClearManagedDict((PyObject*)self);
Обратите внимание, что
tp_clearвызывается не всегда перед освобождением экземпляра. Например, когда подсчёта ссылок достаточно, чтобы определить, что объект больше не используется, циклический сборщик мусора не задействуется, и напрямую вызываетсяtp_dealloc.Поскольку цель функций
tp_clear— разрывать циклы ссылок, очищать содержащиеся объекты, такие как строки или целые числа 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 -
Хотя это поле по-прежнему поддерживается, по возможности вместо него следует использовать
Py_TPFLAGS_MANAGED_WEAKREF.Если экземпляры этого типа допускают слабые ссылки, значение этого поля больше нуля и содержит смещение начала списка слабых ссылок в структуре экземпляра (без учёта заголовка GC, если он есть); это смещение используется функцией
PyObject_ClearWeakRefs()и функциямиPyWeakref_*. Структура экземпляра должна содержать поле типа PyObject*, инициализированное значениемNULL.Не путайте это поле с
tp_weaklist; это начало списка слабых ссылок на сам объект типа.Устанавливать одновременно бит
Py_TPFLAGS_MANAGED_WEAKREFиtp_weaklistoffsetнельзя.Наследование:
Это поле наследуется подклассами, но см. приведённые ниже правила. Подкласс может переопределить это смещение; это означает, что в подклассе используется другое начало списка слабых ссылок, чем в базовом типе. Поскольку начало списка всегда определяется с помощью
tp_weaklistoffset, это не должно создавать проблем.По умолчанию:
Если в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_WEAKREF, тоtp_weaklistoffsetбудет установлено в отрицательное значение, указывающее, что использовать это поле небезопасно.
-
getiterfunc PyTypeObject.tp_iter -
Необязательный указатель на функцию, возвращающую итератор для объекта. Наличие этой функции обычно означает, что экземпляры данного типа являются итерируемыми (хотя последовательности могут быть итерируемыми и без этой функции).
Эта функция имеет ту же сигнатуру, что и
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 -
Необязательный указатель на статический массив структур
PyMethodDef, завершающийсяNULLи объявляющий обычные методы этого типа.Для каждой записи массива в словарь типа (см.
tp_dictниже) добавляется запись, содержащая дескриптор метода.Наследование:
Это поле не наследуется подклассами (методы наследуются с помощью другого механизма).
-
struct PyMemberDef *PyTypeObject.tp_members -
Необязательный указатель на статический массив структур
PyMemberDef, завершающийсяNULLи объявляющий обычные члены данных (поля или слоты) экземпляров этого типа.Для каждой записи массива в словарь типа (см.
tp_dictниже) добавляется запись, содержащая дескриптор члена.Наследование:
Это поле не наследуется подклассами (члены наследуются с помощью другого механизма).
-
struct PyGetSetDef *PyTypeObject.tp_getset -
Необязательный указатель на статический массив структур
PyGetSetDef, завершающийсяNULLи объявляющий вычисляемые атрибуты экземпляров этого типа.Для каждой записи массива в словарь типа (см.
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().Обычно перед вызовом PyType_Ready этому полю следует присвоить
NULL; также ему можно присвоить словарь с начальными атрибутами типа. После инициализации типа функциейPyType_Ready()в этот словарь можно добавлять дополнительные атрибуты типа, только если они не соответствуют перегруженным операциям (например,__add__()). После завершения инициализации типа это поле следует считать доступным только для чтения.Некоторые типы могут не хранить свой словарь в этом слоте. Для получения словаря произвольного типа используйте
PyType_GetDict().Изменено в версии 3.12: Деталь реализации: для встроенных статических типов это поле всегда равно
NULL. Вместо этого словарь таких типов хранится вPyInterpreterState. Для получения словаря произвольного типа используйтеPyType_GetDict().Наследование:
Это поле не наследуется подклассами (однако определённые в нём атрибуты наследуются с помощью другого механизма).
По умолчанию:
Если это поле равно
NULL, функцияPyType_Ready()присвоит ему новый словарь.Предупреждение
Использовать
PyDict_SetItem()для измененияtp_dictили иным образом изменять это поле с помощью C API словарей небезопасно.
-
descrgetfunc PyTypeObject.tp_descr_get -
Необязательный указатель на функцию «получения дескриптора».
Сигнатура функции:
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 -
Хотя это поле по-прежнему поддерживается, по возможности вместо него следует использовать
Py_TPFLAGS_MANAGED_DICT.Если экземпляры этого типа имеют словарь, содержащий переменные экземпляра, значение этого поля отлично от нуля и содержит смещение словаря переменных экземпляра в экземплярах данного типа; это смещение используется функцией
PyObject_GenericGetAttr().Не путайте это поле с
tp_dict; последнее представляет собой словарь атрибутов самого объекта типа.Значение задаёт смещение словаря относительно начала структуры экземпляра.
Поле
tp_dictoffsetследует считать доступным только для записи. Чтобы получить указатель на словарь, вызовитеPyObject_GenericGetDict(). ВызовPyObject_GenericGetDict()может потребовать выделения памяти для словаря, поэтому при доступе к атрибуту объекта может быть эффективнее вызватьPyObject_GetAttr().Устанавливать одновременно бит
Py_TPFLAGS_MANAGED_DICTи полеtp_dictoffsetнельзя.Наследование:
Это поле наследуется подклассами. Подклассу не следует переопределять это смещение: это может быть небезопасно, если код на C попытается обратиться к словарю по прежнему смещению. Для корректной поддержки наследования используйте
Py_TPFLAGS_MANAGED_DICT.Значение по умолчанию:
Для этого слота нет значения по умолчанию. Для статических типов, если значение поля равно
NULL, для экземпляров не создаётся__dict__.Если в поле
tp_flagsустановлен битPy_TPFLAGS_MANAGED_DICT, то полюtp_dictoffsetбудет присвоено значение-1, указывающее на то, что использовать это поле небезопасно.
-
initproc PyTypeObject.tp_init -
Необязательный указатель на функцию инициализации экземпляра.
Эта функция соответствует методу
__init__()классов. Как и в случае с__init__(), экземпляр можно создать, не вызывая__init__(), а также повторно инициализировать, снова вызвав его метод__init__().Сигнатура функции:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
Аргумент self — это инициализируемый экземпляр; аргументы args и kwds представляют позиционные и именованные аргументы вызова
__init__().Функция
tp_init, если она не равнаNULL, вызывается при обычном создании экземпляра вызовом его типа — после того как функция типаtp_newвернула экземпляр этого типа. Если функцияtp_newвозвращает экземпляр другого типа, не являющегося подклассом исходного типа, функцияtp_initне вызывается; если жеtp_newвозвращает экземпляр подкласса исходного типа, вызывается функцияtp_initподкласса.В случае успеха возвращает
0, при ошибке возвращает-1и устанавливает исключение.Наследование:
Это поле наследуется подклассами.
Значение по умолчанию:
Для статических типов у этого поля нет значения по умолчанию.
-
allocfunc PyTypeObject.tp_alloc -
Необязательный указатель на функцию выделения памяти для экземпляра.
Сигнатура функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Это поле наследуется статическими подклассами, но не динамическими подклассами (подклассами, созданными инструкцией class).
Значение по умолчанию:
Для динамических подклассов этому полю всегда присваивается
PyType_GenericAlloc(), чтобы обеспечить стандартную стратегию выделения памяти в куче.Для статических подклассов
PyBaseObject_TypeиспользуетPyType_GenericAlloc(). Это рекомендуемое значение для всех статически определённых типов.
-
newfunc PyTypeObject.tp_new -
Необязательный указатель на функцию создания экземпляра.
Сигнатура функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент 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().Наследование:
Это поле наследуется статическими подклассами, но не динамическими подклассами (подклассами, созданными инструкцией class).
Значение по умолчанию:
Для динамических подклассов этому полю присваивается функция освобождения памяти, совместимая с
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 -
Не используется. Только для внутреннего применения.
Наследование:
Это поле не наследуется.
-
void *PyTypeObject.tp_subclasses -
Коллекция подклассов. Только для внутреннего применения. Может содержать недействительный указатель.
Чтобы получить список подклассов, вызовите метод Python
__subclasses__().Изменено в версии 3.12: Для некоторых типов это поле не содержит допустимый PyObject*. Тип поля был изменён на void*, чтобы это обозначить.
Наследование:
Это поле не наследуется.
-
PyObject *PyTypeObject.tp_weaklist -
Начало списка слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего применения.
Изменено в версии 3.12: Особенность реализации: для некоторых встроенных статических типов это поле всегда равно
NULL, даже если добавлены слабые ссылки. Вместо этого слабые ссылки для каждого из них хранятся вPyInterpreterState. Используйте общедоступный C API или внутренний макрос_PyObject_GET_WEAKREFS_LISTPTR(), чтобы не учитывать это различие.Наследование:
Это поле не наследуется.
-
destructor PyTypeObject.tp_del -
Это поле объявлено устаревшим. Вместо него используйте
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) { /* Save the current exception, if any. */ PyObject *exc = PyErr_GetRaisedException(); /* ... */ /* Restore the saved exception. */ PyErr_SetRaisedException(exc); }Наследование:
Это поле наследуется подклассами.
Добавлено в версии 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)
-
unsigned char PyTypeObject.tp_watched -
Внутреннее поле. Не используйте.
Добавлено в версии 3.12.
Статические типы
Традиционно типы, определённые в коде на C, являются статическими: структура PyTypeObject со статическим временем хранения определяется непосредственно в коде и инициализируется с помощью PyType_Ready().
В результате получаются типы с ограничениями по сравнению с типами, определёнными в Python:
- Статические типы могут иметь только один базовый тип, то есть не поддерживают множественное наследование.
- Объекты статических типов (но не обязательно их экземпляры) неизменяемы. Из Python нельзя добавлять или изменять атрибуты объекта типа.
- Объекты статических типов совместно используются субинтерпретаторами, поэтому они не должны содержать состояние, специфичное для отдельного субинтерпретатора.
Кроме того, поскольку PyTypeObject входит в ограниченный API только как непрозрачная структура, любые модули расширения, использующие статические типы, необходимо компилировать для конкретной младшей версии Python.
Типы в куче
Альтернатива статическим типам — типы, выделяемые в куче, или, короче, типы в куче. Они близки по своей природе к классам, создаваемым инструкцией class в Python. У типов в куче установлен флаг Py_TPFLAGS_HEAPTYPE.
Для этого заполняют структуру PyType_Spec и вызывают PyType_FromSpec(), PyType_FromSpecWithBases(), PyType_FromModuleAndSpec() или PyType_FromMetaclass().
Структуры числовых объектов
-
type PyNumberMethods -
Эта структура содержит указатели на функции, с помощью которых объект реализует числовой протокол. Каждая функция используется функцией с аналогичным именем, описанной в разделе Числовой протокол.
Определение структуры:
typedef struct { binaryfunc nb_add; binaryfunc nb_subtract; binaryfunc nb_multiply; binaryfunc nb_remainder; binaryfunc nb_divmod; ternaryfunc nb_power; unaryfunc nb_negative; unaryfunc nb_positive; unaryfunc nb_absolute; inquiry nb_bool; unaryfunc nb_invert; binaryfunc nb_lshift; binaryfunc nb_rshift; binaryfunc nb_and; binaryfunc nb_xor; binaryfunc nb_or; unaryfunc nb_int; void *nb_reserved; unaryfunc nb_float; binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; binaryfunc nb_inplace_rshift; binaryfunc nb_inplace_and; binaryfunc nb_inplace_xor; binaryfunc nb_inplace_or; binaryfunc nb_floor_divide; binaryfunc nb_true_divide; binaryfunc nb_inplace_floor_divide; binaryfunc nb_inplace_true_divide; unaryfunc nb_index; binaryfunc nb_matrix_multiply; binaryfunc nb_inplace_matrix_multiply; } PyNumberMethods;Примечание
Двоичные и троичные функции должны проверять типы всех операндов и выполнять необходимые преобразования (по крайней мере один из операндов является экземпляром определённого типа). Если операция не определена для заданных операндов, двоичные и троичные функции должны возвращать
Py_NotImplemented; если произошла другая ошибка, они должны возвращатьNULLи устанавливать исключение.Примечание
Поле
nb_reservedвсегда должно иметь значениеNULL. Ранее оно называлосьnb_long; переименование состоялось в Python 3.0.1.
-
binaryfunc PyNumberMethods.nb_add
-
binaryfunc PyNumberMethods.nb_subtract
-
binaryfunc PyNumberMethods.nb_multiply
-
binaryfunc PyNumberMethods.nb_remainder
-
binaryfunc PyNumberMethods.nb_divmod
-
ternaryfunc PyNumberMethods.nb_power
-
unaryfunc PyNumberMethods.nb_negative
-
unaryfunc PyNumberMethods.nb_positive
-
unaryfunc PyNumberMethods.nb_absolute
-
inquiry PyNumberMethods.nb_bool
-
unaryfunc PyNumberMethods.nb_invert
-
binaryfunc PyNumberMethods.nb_lshift
-
binaryfunc PyNumberMethods.nb_rshift
-
binaryfunc PyNumberMethods.nb_and
-
binaryfunc PyNumberMethods.nb_xor
-
binaryfunc PyNumberMethods.nb_or
-
unaryfunc PyNumberMethods.nb_int
-
void *PyNumberMethods.nb_reserved
-
unaryfunc PyNumberMethods.nb_float
-
binaryfunc PyNumberMethods.nb_inplace_add
-
binaryfunc PyNumberMethods.nb_inplace_subtract
-
binaryfunc PyNumberMethods.nb_inplace_multiply
-
binaryfunc PyNumberMethods.nb_inplace_remainder
-
ternaryfunc PyNumberMethods.nb_inplace_power
-
binaryfunc PyNumberMethods.nb_inplace_lshift
-
binaryfunc PyNumberMethods.nb_inplace_rshift
-
binaryfunc PyNumberMethods.nb_inplace_and
-
binaryfunc PyNumberMethods.nb_inplace_xor
-
binaryfunc PyNumberMethods.nb_inplace_or
-
binaryfunc PyNumberMethods.nb_floor_divide
-
binaryfunc PyNumberMethods.nb_true_divide
-
binaryfunc PyNumberMethods.nb_inplace_floor_divide
-
binaryfunc PyNumberMethods.nb_inplace_true_divide
-
unaryfunc PyNumberMethods.nb_index
-
binaryfunc PyNumberMethods.nb_matrix_multiply
-
binaryfunc PyNumberMethods.nb_inplace_matrix_multiply
Структуры отображающих объектов
-
type PyMappingMethods -
Эта структура содержит указатели на функции, с помощью которых объект реализует протокол отображения. Она состоит из трёх элементов:
-
lenfunc PyMappingMethods.mp_length -
Эта функция используется функциями
PyMapping_Size()иPyObject_Size()и имеет ту же сигнатуру. Для объектов, длина которых не определена, этому слоту можно присвоитьNULL.
-
binaryfunc PyMappingMethods.mp_subscript -
Эта функция используется функциями
PyObject_GetItem()иPySequence_GetSlice()и имеет ту же сигнатуру, что иPyObject_GetItem(). Чтобы функцияPyMapping_Check()возвращала1, этот слот должен быть заполнен; в противном случае ему можно присвоитьNULL.
-
objobjargproc PyMappingMethods.mp_ass_subscript -
Эта функция используется функциями
PyObject_SetItem(),PyObject_DelItem(),PySequence_SetSlice()иPySequence_DelSlice(). Она имеет ту же сигнатуру, что иPyObject_SetItem(), но для удаления элемента аргумент v также может быть равенNULL. Если этот слот равенNULL, объект не поддерживает присваивание и удаление элементов.
Структуры объектов последовательностей
-
type PySequenceMethods -
Эта структура содержит указатели на функции, которые объект использует для реализации протокола последовательностей.
-
lenfunc PySequenceMethods.sq_length -
Эта функция используется функциями
PySequence_Size()иPyObject_Size()и имеет ту же сигнатуру. Она также используется для обработки отрицательных индексов через слотыsq_itemиsq_ass_item.
-
binaryfunc PySequenceMethods.sq_concat -
Эта функция используется функцией
PySequence_Concat()и имеет ту же сигнатуру. Она также используется оператором+после попытки выполнить числовое сложение через слотnb_add.
-
ssizeargfunc PySequenceMethods.sq_repeat -
Эта функция используется функцией
PySequence_Repeat()и имеет ту же сигнатуру. Она также используется оператором*после попытки выполнить числовое умножение через слотnb_multiply.
-
ssizeargfunc PySequenceMethods.sq_item -
Эта функция используется функцией
PySequence_GetItem()и имеет ту же сигнатуру. Она также используется функциейPyObject_GetItem()после попытки выполнить операцию индексирования через слотmp_subscript. Этот слот должен быть заполнен, чтобы функцияPySequence_Check()возвращала1; в противном случае он может бытьNULL.Отрицательные индексы обрабатываются следующим образом: если слот
sq_lengthзаполнен, он вызывается, а длина последовательности используется для вычисления положительного индекса, который передаётся вsq_item. Еслиsq_lengthравенNULL, индекс передаётся функции без изменений.
-
ssizeobjargproc PySequenceMethods.sq_ass_item -
Эта функция используется функцией
PySequence_SetItem()и имеет ту же сигнатуру. Она также используется функциямиPyObject_SetItem()иPyObject_DelItem()после попытки выполнить присваивание и удаление элемента через слотmp_ass_subscript. Если объект не поддерживает присваивание и удаление элементов, этот слот можно оставить равнымNULL.
-
objobjproc PySequenceMethods.sq_contains -
Эта функция может использоваться функцией
PySequence_Contains()и имеет ту же сигнатуру. Этот слот можно оставить равнымNULL; в этом случаеPySequence_Contains()просто перебирает последовательность, пока не найдёт совпадение.
-
binaryfunc PySequenceMethods.sq_inplace_concat -
Эта функция используется функцией
PySequence_InPlaceConcat()и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его. Этот слот можно оставить равнымNULL; в этом случаеPySequence_InPlaceConcat()используетPySequence_Concat()в качестве запасного варианта. Он также используется при расширенном присваивании+=после попытки выполнить числовое сложение на месте через слотnb_inplace_add.
-
ssizeargfunc PySequenceMethods.sq_inplace_repeat -
Эта функция используется функцией
PySequence_InPlaceRepeat()и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его. Этот слот можно оставить равнымNULL; в этом случаеPySequence_InPlaceRepeat()используетPySequence_Repeat()в качестве запасного варианта. Он также используется при расширенном присваивании*=после попытки выполнить числовое умножение на месте через слотnb_inplace_multiply.
Структуры буферных объектов
-
type PyBufferProcs -
Эта структура содержит указатели на функции, необходимые для буферного протокола. Протокол определяет, как объект-экспортёр может предоставлять свои внутренние данные объектам-потребителям.
-
getbufferproc PyBufferProcs.bf_getbuffer -
Сигнатура этой функции:
int (PyObject *exporter, Py_buffer *view, int flags);
Обработать запрос к экспортёру на заполнение представления в соответствии с флагами. За исключением пункта (3), реализация этой функции ДОЛЖНА выполнить следующие действия:
- Проверить, можно ли выполнить запрос. Если нет, вызвать исключение
BufferError, установить для view->obj значениеNULLи вернуть-1. - Заполнить запрошенные поля.
- Увеличить внутренний счётчик количества экспортов.
- Установить для view->obj значение экспортёра и увеличить счётчик ссылок на view->obj.
- Вернуть
0.
Если экспортёр входит в цепочку или дерево поставщиков буфера, можно использовать две основные схемы:
- Повторный экспорт: каждый элемент дерева выступает в роли экспортирующего объекта и устанавливает для view->obj новую ссылку на себя.
- Перенаправление: запрос буфера перенаправляется корневому объекту дерева. В этом случае view->obj будет новой ссылкой на корневой объект.
Отдельные поля представления описаны в разделе Структура буфера, а правила реакции экспортёра на конкретные запросы — в разделе Типы запросов буфера.
Вся память, на которую указывает структура
Py_buffer, принадлежит экспортёру и должна оставаться действительной, пока существуют потребители. Поляformat,shape,strides,suboffsetsиinternalдоступны потребителю только для чтения.Функция
PyBuffer_FillInfo()позволяет легко предоставить простой байтовый буфер, корректно обрабатывая все типы запросов.Функция
PyObject_GetBuffer()— это интерфейс потребителя, который оборачивает данную функцию. - Проверить, можно ли выполнить запрос. Если нет, вызвать исключение
-
releasebufferproc PyBufferProcs.bf_releasebuffer -
Сигнатура этой функции:
void (PyObject *exporter, Py_buffer *view);
Обработать запрос на освобождение ресурсов буфера. Если освобождать ресурсы не требуется, значение
PyBufferProcs.bf_releasebufferможет бытьNULL. В противном случае стандартная реализация этой функции может выполнить следующие действия:- Уменьшить внутренний счётчик количества экспортов.
- Если счётчик равен
0, освободить всю память, связанную с представлением.
Экспортёр ДОЛЖЕН использовать поле
internalдля отслеживания ресурсов, связанных с буфером. Это поле гарантированно остаётся неизменным, поскольку потребитель МОЖЕТ передать копию исходного буфера в качестве аргумента представления.Эта функция НЕ ДОЛЖНА уменьшать счётчик ссылок view->obj, поскольку это автоматически выполняется функцией
PyBuffer_Release()(эта схема полезна для разрыва циклических ссылок).Функция
PyBuffer_Release()— это интерфейс потребителя, который оборачивает данную функцию.
Структуры асинхронных объектов
Добавлено в версии 3.5.
-
type PyAsyncMethods -
Эта структура содержит указатели на функции, необходимые для реализации объектов ожидаемого объекта и асинхронного итератора.
Определение структуры:
typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; sendfunc am_send; } PyAsyncMethods;
-
unaryfunc PyAsyncMethods.am_await -
Сигнатура этой функции:
PyObject *am_await(PyObject *self);
Возвращаемый объект должен быть итератором, то есть для него функция
PyIter_Check()должна возвращать1.Если объект не является ожидаемым объектом, этому слоту можно присвоить
NULL.
-
unaryfunc PyAsyncMethods.am_aiter -
Сигнатура этой функции:
PyObject *am_aiter(PyObject *self);
Должна возвращать объект асинхронного итератора. Подробности см. в
__anext__().Если объект не реализует протокол асинхронной итерации, этому слоту можно присвоить
NULL.
-
unaryfunc PyAsyncMethods.am_anext -
Сигнатура этой функции:
PyObject *am_anext(PyObject *self);
Должна возвращать объект ожидаемого объекта. Подробности см. в
__anext__(). Этому слоту можно присвоитьNULL.
-
sendfunc PyAsyncMethods.am_send -
Сигнатура этой функции:
PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);
Подробности см. в
PyIter_Send(). Этому слоту можно присвоитьNULL.Добавлено в версии 3.10.
Определения типов слотов
-
typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems) -
Часть стабильного ABI.
Эта функция предназначена для отделения выделения памяти от её инициализации. Она должна возвращать указатель на блок памяти подходящей длины для экземпляра, выровненный надлежащим образом и заполненный нулями, при этом
ob_refcntдолжен быть установлен в1, аob_type— в аргумент типа. Если значениеtp_itemsizeтипа ненулевое, полеob_sizeобъекта должно быть инициализировано значением nitems, а длина выделенного блока памяти должна составлятьtp_basicsize + nitems*tp_itemsizeс округлением вверх до кратногоsizeof(void*); в противном случае nitems не используется, а длина блока должна быть равнаtp_basicsize.Эта функция не должна выполнять никакую другую инициализацию экземпляра, даже выделять дополнительную память; это должна делать функция
tp_new.
-
typedef void (*destructor)(PyObject*) - Часть стабильного ABI.
-
typedef void (*freefunc)(void*) -
См.
tp_free.
-
typedef PyObject *(*newfunc)(PyTypeObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_new.
-
typedef int (*initproc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_init.
-
typedef PyObject *(*reprfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_repr.
-
typedef PyObject *(*getattrfunc)(PyObject *self, char *attr) -
Часть стабильного ABI.
Возвращает значение именованного атрибута объекта.
-
typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value) -
Часть стабильного ABI.
Устанавливает значение именованного атрибута объекта. Чтобы удалить атрибут, аргумент value устанавливается в
NULL.
-
typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr) -
Часть стабильного ABI.
Возвращает значение именованного атрибута объекта.
См.
tp_getattro.
-
typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value) -
Часть стабильного ABI.
Устанавливает значение именованного атрибута объекта. Чтобы удалить атрибут, аргумент value устанавливается в
NULL.См.
tp_setattro.
-
typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_descr_get.
-
typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*) -
Часть стабильного ABI.
См.
tp_descr_set.
-
typedef Py_hash_t (*hashfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_hash.
-
typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int) -
Часть стабильного ABI.
См.
tp_richcompare.
-
typedef PyObject *(*getiterfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_iter.
-
typedef PyObject *(*iternextfunc)(PyObject*) -
Часть стабильного ABI.
См.
tp_iternext.
-
typedef Py_ssize_t (*lenfunc)(PyObject*) - Часть стабильного ABI.
-
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int) - Часть стабильного ABI начиная с версии 3.12.
-
typedef void (*releasebufferproc)(PyObject*, Py_buffer*) - Часть стабильного ABI начиная с версии 3.12.
-
typedef PyObject *(*unaryfunc)(PyObject*) - Часть стабильного ABI.
-
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**) -
См.
am_send.
-
typedef PyObject *(*ternaryfunc)(PyObject*, PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t) - Часть стабильного ABI.
-
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*) - Часть стабильного ABI.
-
typedef int (*objobjproc)(PyObject*, PyObject*) - Часть стабильного ABI.
-
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*) - Часть стабильного ABI.
Примеры
Ниже приведены простые примеры определений типов Python. Они демонстрируют распространённые случаи использования, с которыми вы можете столкнуться. В некоторых примерах показаны сложные особые случаи. Дополнительные примеры, практическую информацию и руководство см. в разделах Определение типов расширений: руководство и Определение типов расширений: различные темы.
Базовый статический тип:
typedef struct {
PyObject_HEAD
const char *data;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = PyDoc_STR("My objects"),
.tp_new = myobj_new,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
};
В старом коде (особенно в исходном коде CPython) также могут встречаться более подробные инициализаторы:
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mymod.MyObject", /* tp_name */
sizeof(MyObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)myobj_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)myobj_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
PyDoc_STR("My objects"), /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
myobj_new, /* tp_new */
};
Тип, поддерживающий слабые ссылки, словари экземпляров и хеширование:
typedef struct {
PyObject_HEAD
const char *data;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = PyDoc_STR("My objects"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
Py_TPFLAGS_MANAGED_WEAKREF,
.tp_new = myobj_new,
.tp_traverse = (traverseproc)myobj_traverse,
.tp_clear = (inquiry)myobj_clear,
.tp_alloc = PyType_GenericNew,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
.tp_hash = (hashfunc)myobj_hash,
.tp_richcompare = PyBaseObject_Type.tp_richcompare,
};
Подкласс str, который нельзя наследовать и нельзя вызывать для создания экземпляров (например, использующий отдельную фабричную функцию), с флагом Py_TPFLAGS_DISALLOW_INSTANTIATION:
typedef struct {
PyUnicodeObject raw;
char *extra;
} MyStr;
static PyTypeObject MyStr_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyStr",
.tp_basicsize = sizeof(MyStr),
.tp_base = NULL, // set to &PyUnicode_Type in module init
.tp_doc = PyDoc_STR("my custom str"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.tp_repr = (reprfunc)myobj_repr,
};
Самый простой статический тип с экземплярами фиксированной длины:
typedef struct {
PyObject_HEAD
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
};
Самый простой статический тип с экземплярами переменной длины:
typedef struct {
PyObject_VAR_HEAD
const char *data[1];
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject) - sizeof(char *),
.tp_itemsize = sizeof(char *),
};
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/c-api/typeobj.html