Объекты типов
Возможно, одна из важнейших структур объектной системы 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__ | ||
определения типов слотов
определение типа | Типы параметров | Тип возвращаемого значения |
|---|---|---|
| ||
| void | |
void * | void | |
int | ||
| ||
int | ||
|
| |
| ||
int | ||
| ||
int | ||
| ||
int | ||
| Py_hash_t | |
| ||
|
| |
|
| |
| ||
int | ||
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;
/* 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()не изменяет это поле, если оно не равно нулю.Наследование:
Это поле наследуется подклассами.
-
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 -
Указатель на строку, завершающуюся NUL и содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, за которым следует точка, а затем имя типа; для встроенных типов в ней должно быть только имя типа. Если модуль является подмодулем пакета, полное имя пакета входит в полное имя модуля. Например, тип с именем
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.Экземпляры типа с переменной длиной должны иметь поле
ob_size, а размер экземпляра равенtp_basicsizeплюс N, умноженное наtp_itemsize, где N — «длина» объекта. Значение N обычно хранится в полеob_sizeэкземпляра. Есть исключения: например, для обозначения отрицательного числа объекты типа int используют отрицательное значениеob_size, и в этом случае N равноabs(ob_size). Кроме того, наличие поляob_sizeв структуре экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура типа list имеет экземпляры фиксированной длины, но у этих экземпляров есть значимое полеob_size).Базовый размер включает поля экземпляра, объявленные макросом
PyObject_HEADилиPyObject_VAR_HEAD(в зависимости от того, какой макрос используется для объявления структуры экземпляра); в свою очередь, они включают поля_ob_prevи_ob_next, если те присутствуют. Это означает, что единственный правильный способ получить значение для инициализатораtp_basicsize— использовать операторsizeofдля структуры, применяемой для объявления компоновки экземпляра. Базовый размер не включает размер заголовка GC.Примечание о выравнивании: если элементы переменной длины требуют определённого выравнивания, это необходимо обеспечить значением
tp_basicsize. Пример: предположим, что тип реализует массив изdouble.tp_itemsizeравноsizeof(double). Программист должен обеспечить, чтобыtp_basicsizeбыло кратноsizeof(double)(если это требование к выравниванию дляdouble).Для любого типа с экземплярами переменной длины это поле не должно быть
NULL.Наследование:
Подклассы наследуют эти поля независимо друг от друга. Если базовый тип имеет ненулевое значение
tp_itemsize, обычно небезопасно задавать в подклассе другое ненулевое значениеtp_itemsize(хотя это зависит от реализации базового типа).
-
destructor PyTypeObject.tp_dealloc -
Указатель на функцию-деструктор экземпляра. Эта функция должна быть определена, если только тип не гарантирует, что его экземпляры никогда не будут освобождены (как в случае одиночных объектов
NoneиEllipsis). Сигнатура функции:void tp_dealloc(PyObject *self);
Функция-деструктор вызывается макросами
Py_DECREF()иPy_XDECREF(), когда новое значение счётчика ссылок становится равным нулю. В этот момент экземпляр ещё существует, но ссылок на него уже нет. Функция-деструктор должна освободить все ссылки, принадлежащие экземпляру, освободить все буферы памяти, принадлежащие экземпляру (используя функцию освобождения, соответствующую функции выделения памяти, с помощью которой был выделен буфер), и вызвать функциюtp_freeтипа. Если тип нельзя наследовать (у него не установлен бит флагаPy_TPFLAGS_BASETYPE), вместо вызоваtp_freeдопускается напрямую вызвать функцию освобождения объекта. Следует использовать ту функцию освобождения объекта, которая применялась при выделении экземпляра; обычно этоPyObject_Del(), если экземпляр был выделен с помощьюPyObject_NewилиPyObject_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, а не только из потока, создавшего объект (если объект становится частью цикла ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Для вызовов API Python это не проблема, поскольку поток, в котором вызывается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.
-
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 -
Этот бит указывает, что у экземпляров класса есть атрибут
~object.__dict__, а пространство для словаря управляется виртуальной машиной.Если установлен этот флаг, следует также установить
Py_TPFLAGS_HAVE_GC.Добавлено в версии 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 и потому не может входить в цикл ссылок.С другой стороны, даже если вы знаете, что член не может входить в цикл, в целях отладки его можно всё же обойти, чтобы функция
gcмодуляget_referents()включала его в результат.Предупреждение
При реализации
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_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().Обычно это поле следует инициализировать значением
NULLдо вызова PyType_Ready; его также можно инициализировать словарём, содержащим начальные атрибуты типа. После инициализации типа функциейPyType_Ready()в этот словарь можно добавлять дополнительные атрибуты типа, только если они не соответствуют перегруженным операциям (например,__add__()). После завершения инициализации типа это поле следует считать доступным только для чтения.Некоторые типы могут не хранить свой словарь в этом слоте. Для получения словаря произвольного типа используйте
PyType_GetDict().Изменено в версии 3.12: Подробность реализации: для встроенных статических типов это значение всегда равно
NULL. Вместо этого словарь таких типов хранится вPyInterpreterState. Чтобы получить словарь произвольного типа, используйтеPyType_GetDict().Наследование:
Это поле не наследуется подклассами (хотя определённые в нём атрибуты наследуются с помощью другого механизма).
По умолчанию:
Если это поле равно
NULL,PyType_Ready()присвоит ему новый словарь.Предупреждение
Использовать
PyDict_SetItem()для измененияtp_dictили иным образом изменять это поле с помощью C API словарей небезопасно.
-
descrgetfunc PyTypeObject.tp_descr_get -
Необязательный указатель на функцию «получения дескриптора».
Сигнатура функции:
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_dictустановлен бит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 -
Кортеж, содержащий расширенный набор базовых типов в порядке разрешения методов (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) { 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); }Наследование:
Это поле наследуется подклассами.
Добавлено в версии 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);
Обработать запрос к экспортёру на заполнение view согласно flags. За исключением пункта (3), реализация этой функции ОБЯЗАНА выполнить следующие действия:
- Проверить, можно ли удовлетворить запрос. Если это невозможно, вызвать исключение
BufferError, присвоить view->obj значениеNULLи вернуть-1. - Заполнить запрошенные поля.
- Увеличить внутренний счётчик количества экспортов.
- Присвоить view->obj значение exporter и увеличить значение view->obj.
- Вернуть
0.
Если exporter является частью цепочки или дерева поставщиков буфера, можно использовать две основные схемы:
- Повторный экспорт: каждый элемент дерева выступает в роли экспортирующего объекта и присваивает view->obj новую ссылку на себя.
- Перенаправление: запрос буфера перенаправляется корневому объекту дерева. В этом случае view->obj будет новой ссылкой на корневой объект.
Отдельные поля view описаны в разделе Структура буфера, а правила, определяющие, как экспортёр должен реагировать на конкретные запросы, приведены в разделе Типы запросов буфера.
Вся память, на которую указывают указатели в структуре
Py_buffer, принадлежит экспортёру и должна оставаться действительной, пока существуют потребители. Поляformat,shape,strides,suboffsetsиinternalдоступны потребителю только для чтения.PyBuffer_FillInfo()позволяет легко предоставить простой буфер байтов с корректной обработкой всех типов запросов.PyObject_GetBuffer()— интерфейс для потребителя, обёртывающий эту функцию. - Проверить, можно ли удовлетворить запрос. Если это невозможно, вызвать исключение
-
releasebufferproc PyBufferProcs.bf_releasebuffer -
Сигнатура этой функции:
void (PyObject *exporter, Py_buffer *view);
Обработать запрос на освобождение ресурсов буфера. Если освобождать ресурсы не требуется,
PyBufferProcs.bf_releasebufferможет иметь значениеNULL. В противном случае стандартная реализация этой функции может выполнить следующие действия:- Уменьшить внутренний счётчик количества экспортов.
- Если счётчик равен
0, освободить всю память, связанную с view.
Экспортёр ОБЯЗАН использовать поле
internalдля отслеживания ресурсов, относящихся к буферу. Это поле гарантированно остаётся неизменным, даже если потребитель передаст копию исходного буфера в качестве аргумента view.Эта функция НЕ ДОЛЖНА уменьшать значение view->obj, поскольку это автоматически выполняется в
PyBuffer_Release()(эта схема полезна для разрыва циклов ссылок).PyBuffer_Release()— интерфейс для потребителя, обёртывающий эту функцию.
Структуры асинхронных объектов
Добавлено в версии 3.5.
-
type PyAsyncMethods -
Эта структура содержит указатели на функции, необходимые для реализации объектов ожидаемого объекта и асинхронного итератора.
Определение структуры:
typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; sendfunc am_send; } PyAsyncMethods;
-
unaryfunc PyAsyncMethods.am_await -
Сигнатура этой функции:
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 слотов
-
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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/c-api/typeobj.html