Объекты типа¶
Возможно, одной из важнейших структур Python объектной системы является
структура, определяющая новый тип: структура PyTypeObject
. Объекты типа могут
обрабатываться с помощью любой из PyObject_*()
или PyType_*()
функций, но не
предлагают много интересного для большинства Python приложений. Эти объекты
имеют основополагающее значение для поведения объектов, поэтому они очень важны
для самого интерпретатора и для любого модуля расширения, реализующего новые типы.
Объекты типа довольно велики по сравнению с большинством стандартных типов. Причина размера в том, что каждый объект типа хранит большое количество значения, в основном указателей функций C, каждый из которых реализует небольшую часть функциональности типа. В этом разделе подробно рассматриваются поля объекта типа. Поля будут описаны в порядке их появления в структуре.
В дополнение к следующему краткому справочнику, Примеры раздел предоставляет
краткое представление о значении и использовании PyTypeObject
.
Краткий справочник¶
«слоты tp»¶
Если COUNT_ALLOCS
определено, то также существуют следующие (только внутренние)
поля:
[1] | Имя слота в скобках указывает на то, что оно (фактически) устарело.
Имена в угловых скобках должны рассматриваться как доступные только для чтения.
Имена в квадратных скобках предназначены только для внутреннего использования.
«<R>» (в качестве префикса) означает, что поле является обязательным (должно
быть не NULL ). |
[2] | Колонки: «O»: установка на «T»: установка на «D»: по умолчанию (если для слота установлено значение X - PyType_Ready устанавливает значение, если оно равно NULL
~ - PyType_Ready всегда устанавливает значение (оно должно быть NULL)
? - PyType_Ready может установить значение в зависимости от других слотов
См. также столбец наследования ("I").
«I»: наследование X - слот типа наследуется через PyType_Ready, если он определен со значением NULL
% - слоты субструктуры наследуются индивидуально
G - наследуется, но только в сочетании с другими слотами; см. описание слота
? - это сложно; см. описание слота
Следует отметить, что некоторые слоты эффективно наследуются через обычную цепочку поиска атрибута. |
подслоты¶
typedefs слотов¶
typedef | Типы параметров | Возвращаемый тип |
---|---|---|
allocfunc |
Py_ssize_t
|
PyObject * |
destructor |
void * | void |
freefunc |
void * | void |
traverseproc |
int | |
newfunc |
PyObject * |
|
initproc |
int | |
reprfunc |
PyObject * |
PyObject * |
getattrfunc |
PyObject *const char *
|
PyObject * |
setattrfunc |
int | |
getattrofunc |
PyObject * |
|
setattrofunc |
int | |
descrgetfunc |
PyObject * |
|
descrsetfunc |
int | |
hashfunc |
PyObject * |
Py_hash_t |
richcmpfunc |
PyObject * |
|
getiterfunc |
PyObject * |
PyObject * |
iternextfunc |
PyObject * |
PyObject * |
lenfunc |
PyObject * |
Py_ssize_t |
getbufferproc |
int | |
releasebufferproc |
void | |
inquiry |
void * | int |
unaryfunc |
PyObject * |
PyObject * |
binaryfunc |
PyObject * |
|
ternaryfunc |
PyObject * |
|
ssizeargfunc |
PyObject *Py_ssize_t
|
PyObject * |
ssizeobjargproc |
PyObject *Py_ssize_t
|
int |
objobjproc |
int | |
objobjargproc |
int |
Для получения более подробной информации см. Тип слота typedefs ниже.
Определение объекта PyTypeObject¶
Определение структуры для PyTypeObject
можно найти в Include/object.h
.
Для удобства, ссылку повторяющую определение, найдете здесь:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag;
destructor tp_finalize;
} PyTypeObject;
Слоты PyObject¶
Структура объекта типа расширяет структуру PyVarObject
. Поле ob_size
используется для динамических типов (создается type_new()
, обычно вызывается из
инструкции class). Обратите внимание, что PyType_Type
(метатип) инициализирует
tp_itemsize
, что означает, что его сущности (т.е. объекты типа) должны
иметь поле ob_size
.
-
PyObject*
PyObject._ob_next
¶ -
PyObject *
PyObject._ob_prev
¶ Эти поля присутствуют только при определении
Py_TRACE_REFS
макросов. Об их инициализации вNULL
заботится макросPyObject_HEAD_INIT
. Для статически аллоцированных объектов эти поля всегда остаютсяNULL
. Для динамически аллоцированных объектов эти два поля используются для связывания объекта с двухсвязным списком всех живых объектов в куче. Это может быть используемо для различных целей отладки; в настоящее время единственным способом использования является печать объектов, которые все еще находятся в рабочем состоянии в конце запуска при установке переменной средыPYTHONDUMPREFS
.Наследование:
Эти поля не наследуются подтипами.
-
Py_ssize_t
PyObject.ob_refcnt
¶ Это число ссылок на объект типа, инициализированное
1
для макросаPyObject_HEAD_INIT
. Обратите внимание, что для статически аллоцированных объектов типа сущности типа (объекты,ob_type
которых указывает на тип) не подсчитываются ссылки. Но для динамически аллоцированных объектов типа, производится подсчет ссылок на экземпляры.Наследование:
Это поле не наследуется подтипами.
-
PyTypeObject*
PyObject.ob_type
¶ Это тип типа, другими словами, его метатип. Он инициализируется аргументом
PyObject_HEAD_INIT
макроса, и его значение обычно&PyType_Type
. Однако для динамически загружаемых модулей расширения, которые должны использоваться в Windows (по крайней мере), компилятор жалуется, что это недопустимый инициализатор. Поэтому соглашение должно передаватьNULL
макросуPyObject_HEAD_INIT
и явно инициализировать это поле в начале функции инициализации модуля, прежде чем делать что-либо другое. Обычно это делается так:Foo_Type.ob_type = &PyType_Type;
Это необходимо сделать до создания любой сущности данного типа.
PyType_Ready()
проверяет, является лиob_type
NULL
, и если да, инициализирует его в полеob_type
базового класса.PyType_Ready()
не изменит это поле, если оно не равно нулю.Наследование:
Это поле наследуется подтипами.
Слоты PyVarObject¶
-
Py_ssize_t
PyVarObject.ob_size
¶ Для статически аллоцированных объектов типа это значение должно быть равно нулю. Для динамически аллоцированных объектов типа - это поле имеет особое внутреннее значение.
Наследование:
Это поле не наследуется подтипами.
Слоты PyTypeObject¶
Каждый слот имеет раздел, описывающий наследование. Если PyType_Ready()
может
установить значение, если в поле установлено значение NULL
то также
будет раздел «По умолчанию». (Обратите внимание, что многие поля, установленные
на PyBaseObject_Type
и PyType_Type
, эффективно действуют как значения по умолчанию.)
-
const char*
PyTypeObject.tp_name
¶ Указатель на строку с NUL окончанием, содержащей имя типа. Для типов, доступных в качестве глобальных модулей, строка должна быть полным именем модуля, за которым следует точка, за которой следует имя типа; для встроенных типов это должно быть только имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип с именем
T
, определенный в модулеM
в подпакетеQ
в пакетеP
, должен иметь"P.Q.M.T"
инициализаторtp_name
.Для динамически аллоцированных объектов типа это должно быть только имя типа и имя модуля, явно сохраненное в словаре типа в качестве значения для
'__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
в макете сущности не означает, что структура сущности имеет переменную длину (например, структура для типа списка имеет фиксированную длину сущности, но эти сущности имеют значимое полеob_size
).Основной размер включает поля в сущности, объявленный макросом
PyObject_HEAD
илиPyObject_VAR_HEAD
(какой бы ни используются, чтобы объявить структуру сущности), и это в свою очередь включает_ob_prev
и поля_ob_next
, если они присутствуют. Это означает, что единственным правильным способом получения инициализатора дляtp_basicsize
является использование оператораsizeof
на используются структуры для объявления формата сущности. Базовый размер не включает размер заголовка GC.Примечание о выравнивании: если переменные элементы требуют определенного выравнивания, об этом должено позаботиться значение
tp_basicsize
. Пример: предположим, что тип реализует массивdouble
.tp_itemsize
- этоsizeof(double)
. Ответственность программиста заключается в том, чтоtp_basicsize
кратноsizeof(double)
(при условии, что это требование выравнивания дляdouble
).Для любого типа с сущности переменной длины это поле не должно быть
NULL
.Наследование:
Эти поля наследуются отдельно подтипами. Если базовый тип имеет ненулевое
tp_itemsize
, то, как правило, небезопасно устанавливатьtp_itemsize
на другое ненулевое значение в подтипе (хотя это зависит от реализации базового типа).
-
destructor
PyTypeObject.tp_dealloc
¶ Указатель на функцию деструктора сущности. Функция должна быть определена, если тип не гарантирует, что ее сущности никогда не будет освобождена (как в случае одиночных
None
иEllipsis
). Сигнатура функции:void tp_dealloc(PyObject *self);
Функция деструктора вызывается макросами
Py_DECREF()
иPy_XDECREF()
, когда количество новых ссылок равно нулю. На данный момент сущность все еще существует, но ссылок на нее нет. Функция деструктора должна освободить все ссылки, которыми владеет сущность, освободить все буферы памяти, принадлежащие сущности (используя функцию освобождения, соответствующую функции распределения используются для аллокация буфера), и вызвать функциюtp_free
типа. Если тип не является подтипируемым (не имеет установленного бита флагаPy_TPFLAGS_BASETYPE
), разрешается вызывать деаллокатор объекта напрямую, а не черезtp_free
. Деаллокатор объекта должен использоваться для аллокации сущности; обычно этоPyObject_Del()
, если сущность была аллоцирована с использованиемPyObject_New()
илиPyObject_VarNew()
, илиPyObject_GC_Del()
если сущность была аллоцирована с использованиемPyObject_GC_New()
илиPyObject_GC_NewVar()
.Наконец, если типом является аллоцированная куча (
Py_TPFLAGS_HEAPTYPE
), деаллокатор должен уменьшить число ссылок для своего объекта типа после вызова деаллокатора типа. Во избежание болтающихся указателей рекомендуется:static void foo_dealloc(foo_object *self) { PyTypeObject *tp = Py_TYPE(self); // здесь свободные ссылки и буферы tp->tp_free(self); Py_DECREF(tp); }
Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_vectorcall_offset
¶ Необязательное смещение до функции на каждую сущность, которая реализует вызов объекта с использованием протокола vectorcall, более эффективной альтернативы более простого
tp_call
.Это поле используются только в том случае, если установлен флаг
_Py_TPFLAGS_HAVE_VECTORCALL
. Если это так, это должно быть положительное целое число, содержащее смещение в сущности указателяvectorcallfunc
. Это та же сигнатура, что и для_PyObject_Vectorcall()
:PyObject *vectorcallfunc(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Указатель vectorcallfunc может быть равен нулю, и в этом случае сущность ведет себя так, как если бы
_Py_TPFLAGS_HAVE_VECTORCALL
не был установлен: вызов сущности возвращается кtp_call
.Любой класс, задающий
_Py_TPFLAGS_HAVE_VECTORCALL
, должен также задатьtp_call
и убедиться, что его поведение соответствует функции vectorcallfunc. Это можно сделать, установив для tp_call значениеPyVectorcall_Call
:-
PyObject *
PyVectorcall_Call
(PyObject *callable, PyObject *tuple, PyObject *dict)¶ Вызов vectorcallfunc callable с позиционными и ключевыми аргументами, приведенными в кортеже и словаре соответственно.
Функция предназначена для использования в слоте
tp_call
. Она не возвращается кtp_call
и в настоящее время не проверяет флаг_Py_TPFLAGS_HAVE_VECTORCALL
. Для вызова объекта используйте одну изPyObject_Call
функций.
Примечание
Не рекомендуется типам кучи реализовывать протокол vectorcall. Когда пользователь устанавливает
__call__
в Python коде, обновляется толькоtp_call
, что может привести к несоответствию функции vectorcall.Примечание
Семантика слота
tp_vectorcall_offset
носит предварительный характер и, как ожидается, будет завершена в Python 3.9. Если используется векторколл, запланируйте обновление код для Python 3.9.Изменено в версии 3.8: Этот слот был используются для форматирования печати в файле Python 2.x. В Python 3.0 до 3.7 он был зарезервирован и назван
tp_print
.Наследование:
Это поле наследуется подтипами вместе с
tp_call
: подтип наследуетtp_vectorcall_offset
от своего базового типа приNULL
tp_call
подтипа.Обратите внимание, что Типы кучи (включая подклассы, определенные в Python) не наследуют флаг
_Py_TPFLAGS_HAVE_VECTORCALL
.-
PyObject *
-
getattrfunc
PyTypeObject.tp_getattr
¶ Необязательный указатель на функцию получения-атрибута-строки.
Это поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_getattro
, но принимает C строку вместо объекта Python строки, чтобы дать имя атрибуту.Наследование:
Группа:
tp_getattr
,tp_getattro
Это поле наследуется подтипами вместе с
tp_getattro
: подтип наследует обаtp_getattr
иtp_getattro
от своего базового типа, когдаtp_getattr
иtp_getattro
подтипа являютсяNULL
.
-
setattrfunc
PyTypeObject.tp_setattr
¶ Необязательный указатель на функцию для установки и удаления атрибутов.
Это поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_setattro
, но принимает C строку вместо объекта строки Python, чтобы дать имя атрибута.Наследование:
Группа:
tp_setattr
,tp_setattro
Это поле наследуется подтипами вместе с
tp_setattro
: подтип наследует обаtp_setattr
иtp_setattro
от своего базового типа, когдаtp_setattr
иtp_setattro
подтипа являютсяNULL
.
-
PyAsyncMethods*
PyTypeObject.tp_as_async
¶ Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим протоколы awaitable и асинхронный итератор на C-уровне. Дополнительные сведения см. в разделе Асинхронные структуры объектов.
Добавлено в версии 3.5: Ранее известна как
tp_compare
иtp_reserved
.Наследование:
Поле
tp_as_async
не наследуется, но содержащиеся поля наследуются по отдельности.
-
reprfunc
PyTypeObject.tp_repr
¶ Необязательный указатель на функцию, реализующую встроенную функцию
repr()
.Та же сигнатура, что и для
PyObject_Repr()
:PyObject *tp_repr(PyObject *self);
Функция должна возвращать объект строки или Юникода. В идеале эта функция должна возвращать строку, которая при передаче
eval()
, учитывая подходящую среду, возвращает объект с тем же значением. Если это невозможно, она должна возвращать строку, начинающийся с'<'
и заканчивающийся'>'
, из которого можно вывести и тип, и значение объекта.Наследование:
Это поле наследуется подтипами.
По умолчанию:
Если это поле не задано, возвращается строка формы
<%s object at %p>
, где%s
заменяется именем типа, а%p
адресом памяти объекта.
-
PyNumberMethods*
PyTypeObject.tp_as_number
¶ Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим протокол номеров. Эти поля задокументированы в Числовые структуры объектов.
Наследование:
Поле
tp_as_number
не наследуется, но содержащиеся поля наследуются по отдельности.
-
PySequenceMethods*
PyTypeObject.tp_as_sequence
¶ Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим протокол последовательности. Эти поля задокументированы в Последовательность структур объектов.
Наследование:
Поле
tp_as_sequence
не наследуется, но содержащиеся поля наследуются по отдельности.
-
PyMappingMethods*
PyTypeObject.tp_as_mapping
¶ Указатель на дополнительную структуру, которая содержит поля, относящиеся только к объектам, реализующим протокол отображения. Эти поля задокументированы в Сопоставление структур объектов.
Наследование:
Поле
tp_as_mapping
не наследуется, но содержащиеся поля наследуются по отдельности.
-
hashfunc
PyTypeObject.tp_hash
¶ Необязательный указатель на функцию, реализующую встроенную функцию
hash()
.Этот сигнатура такая же, что и для
PyObject_Hash()
:Py_hash_t tp_hash(PyObject *);
Значение
-1
не должно быть возвращено как нормальное возвращаемое значение; при возникновении ошибки при вычислении хеш-значения, функция должна установить исключение и возвратить-1
.Если это поле не задано (и
tp_richcompare
не задано), попытка взять хэш объекта вызываетTypeError
. Это то же самое, что установить для него значениеPyObject_HashNotImplemented()
.Для этого поля можно явно установить значение
PyObject_HashNotImplemented()
, чтобы блокировать наследование хэш-метода от родительского типа. Это интерпретируется как эквивалент__hash__ = None
на уровне Python, вызываяisinstance(o, collections.Hashable)
как правильно возвращаетFalse
. Обратите внимание, что обратное также верно - установка__hash__ = None
класса на Python уровне приведет к тому, чтоtp_hash
слот будет установлен вPyObject_HashNotImplemented()
.Наследование:
Группа:
tp_hash
,tp_richcompare
Это поле наследуется подтипами вместе с
tp_richcompare
: подтип наследует иtp_richcompare
, иtp_hash
, когдаtp_richcompare
иtp_hash
подтипа являютсяNULL
.
-
ternaryfunc
PyTypeObject.tp_call
¶ Необязательный указатель на функцию, реализующую вызов объекта. Это должен быть
NULL
, если объект не является вызываемым. Это та же сигнатура, что и дляPyObject_Call()
:PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);
Наследование:
Это поле наследуется подтипами.
-
reprfunc
PyTypeObject.tp_str
¶ Необязательный указатель на функцию, реализующую встроенной
str()
операций. (Обратите внимание, что сейчасstr
является типом, иstr()
вызывает конструктор для этого типа. Этот конструктор вызываетPyObject_Str()
для выполнения фактической работы, аPyObject_Str()
вызывает обработчик.)Та же сигнатура, что и для
PyObject_Str()
:PyObject *tp_str(PyObject *self);
Функция должна возвратить объект строки или Юникода. Это должна быть «дружественное» строке представление объекта, так как это представление, которое будет используются, среди прочего, функцией
print()
.Наследование:
Это поле наследуется подтипами.
По умолчанию:
Если это поле не установлено, вызывается
PyObject_Repr()
для возвращения строки представления.
-
getattrofunc
PyTypeObject.tp_getattro
¶ Необязательный указатель на функцию получения-атрибута.
Та же сигнатура, что и для
PyObject_GetAttr()
:PyObject *tp_getattro(PyObject *self, PyObject *attr);
Обычно удобно установить для этого поля значение
PyObject_GenericGetAttr()
, которое реализует обычный способ поиска атрибутов объектов.Наследование:
Группа:
tp_getattr
,tp_getattro
Это поле наследуется подтипами вместе с
tp_getattr
: подтип наследует обаtp_getattr
иtp_getattro
от своего базового типа, когдаtp_getattr
иtp_getattro
подтипа являютсяNULL
.По умолчанию:
PyBaseObject_Type
используетPyObject_GenericGetAttr()
.
-
setattrofunc
PyTypeObject.tp_setattro
¶ Необязательный указатель на функцию для установки и удаления атрибутов.
Та же сигнатура, что и для
PyObject_SetAttr()
:PyObject *tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
Кроме того, должен поддерживаться параметр value
NULL
для удаления атрибута. Обычно удобно устанавливать для этого поля значениеPyObject_GenericSetAttr()
, которое реализует обычный способ установки атрибута объекта.Наследование:
Группа:
tp_setattr
,tp_setattro
Это поле наследуется подтипами вместе с
tp_setattr
: подтип наследует обаtp_setattr
иtp_setattro
от своего базового типа, когдаtp_setattr
иtp_setattro
подтипа являютсяNULL
.По умолчанию:
PyBaseObject_Type
используетPyObject_GenericSetAttr()
.
-
PyBufferProcs*
PyTypeObject.tp_as_buffer
¶ Указатель на дополнительную структуру, содержащую поля, относящиеся только к объектам, реализующим интерфейс буфера. Эти поля задокументированы в Буферные структуры объектов.
Наследование:
Поле
tp_as_buffer
не наследуется, но содержащиеся поля наследуются по отдельности.
-
unsigned long
PyTypeObject.tp_flags
¶ Это поле является битовой маской различных флагов. Некоторые флаги указывают на семантику вариантов для определенных ситуаций; другие используются чтобы указать, что некоторые поля объекте типа (или в структурах расширений, указанных через
tp_as_number
,tp_as_sequence
,tp_as_mapping
иtp_as_buffer
), которые исторически не всегда присутствовали, являются действительными; если такой бит флага очищен, поля типа, которые он охраняет, не должны быть доступны и должны рассматриваться как имеющие нулевое илиNULL
значение.Наследование:
Наследование этого поля является сложным. Большинство битов флага наследуются по отдельности, т.е. если базовый тип имеет установленный бит флага, подтип наследует этот бит флага. Биты флага, которые относятся к структурам расширения, строго наследуются, если структура расширения наследуется, то есть значение базового типа бита флага копируется в подтип вместе с указателем на структуру расширения. Битовый флаг
Py_TPFLAGS_HAVE_GC
, унаследован вместе сtp_traverse
и полямиtp_clear
, т.е. если флагPy_TPFLAGS_HAVE_GC
, чист в подтипе иtp_traverse
, и поляtp_clear
в подтипе существуют и имеютNULL
значения.По умолчанию:
PyBaseObject_Type
используетPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
.Битовые маски:
В настоящее время определены следующие битовые маски: они могут быть совмещены с помощью оператора
|
для формирования значения поляtp_flags
. МакросPyType_HasFeature()
принимает тип и флаги значение, tp и f и проверяет, не является лиtp->tp_flags & f
ненулевым.-
Py_TPFLAGS_HEAPTYPE
¶ Бит устанавливается при аллоцировании самого объекта типа в кучу, например, типов, созданных динамически с помощью
PyType_FromSpec()
. В этом случае полеob_type
его сущности считается ссылкой на тип, а объект типа - INCREF при создании нового сущности и DECRF при уничтожении сущности (это не относится к сущности подтипов; только тип, на который ссылается ob_type сущности, получает INCREF или DECREF).Наследование:
???
-
Py_TPFLAGS_BASETYPE
¶ Бит устанавливается, когда тип может быть использован как базовый тип другого типа. Если этот бит чист, тип не может быть подтипом (аналогично «конечному» классу в Java).
Наследование:
???
-
Py_TPFLAGS_READY
¶ Бит устанавливается, когда объект типа был полностью инициализирован
PyType_Ready()
.Наследование:
???
-
Py_TPFLAGS_READYING
¶ Бит устанавливается, пока
PyType_Ready()
находится в процессе инициализации объекта типа.Наследование:
???
-
Py_TPFLAGS_HAVE_GC
¶ Бит устанавливается, когда объект поддерживает сбор мусора. Если этот бит установлен, сущности должны быть созданы с помощью
PyObject_GC_New()
и уничтожены с помощьюPyObject_GC_Del()
. Подробнее в разделе Поддержка циклической сборки мусора. Бит также подразумевает, что связанные с GC поляtp_traverse
иtp_clear
присутствуют в объекте-типе.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC
,tp_traverse
,tp_clear
Флаг
Py_TPFLAGS_HAVE_GC
, унаследован вместе сtp_traverse
и полямиtp_clear
, т.е. если флагPy_TPFLAGS_HAVE_GC
, чист в подтипе иtp_traverse
, и поляtp_clear
в подтипе существуют и имеютNULL
значения.
-
Py_TPFLAGS_DEFAULT
¶ Битовая маска всех битов, относящихся к существованию определенных полей в объекте типа и его структурах расширения. В настоящее время включает в себя следующие биты:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION
,Py_TPFLAGS_HAVE_VERSION_TAG
.Наследование:
???
-
Py_TPFLAGS_METHOD_DESCRIPTOR
¶ Бит указывает, что объекты ведут себя как несвязанные методы.
Если этот флаг установлен для
type(meth)
, то:meth.__get__(obj, cls)(*args, **kwds)
(сobj
не None) должен быть эквивалентенmeth(obj, *args, **kwds)
.meth.__get__(None, cls)(*args, **kwds)
должен быть эквивалентенmeth(*args, **kwds)
.
Этот флаг позволяет оптимизировать типичные вызовы методов, такие как
obj.meth()
: он позволяет избежать создания временного объекта «связанного метода» дляobj.meth
.Добавлено в версии 3.8.
Наследование:
Флаг никогда не наследуется типами кучи. Для типов расширений он наследуется всякий раз, когда
tp_descr_get
наследуется.
-
Py_TPFLAGS_LONG_SUBCLASS
¶
-
Py_TPFLAGS_LIST_SUBCLASS
¶
-
Py_TPFLAGS_TUPLE_SUBCLASS
¶
-
Py_TPFLAGS_BYTES_SUBCLASS
¶
-
Py_TPFLAGS_UNICODE_SUBCLASS
¶
-
Py_TPFLAGS_DICT_SUBCLASS
¶
-
Py_TPFLAGS_BASE_EXC_SUBCLASS
¶
-
Py_TPFLAGS_TYPE_SUBCLASS
¶ Флаги используются такими функциями, как
PyLong_Check()
, чтобы быстро определить, является ли тип подклассом встроенного типа; такие конкретные проверки выполняются быстрее, чем общая проверка, например,PyObject_IsInstance()
. Пользовательские типы, наследующие от встроенных, должны иметь соответствующий наборtp_flags
, или код, взаимодействующий с такими типами, будет вести себя по-разному в зависимости от того, какая проверка используются.
-
Py_TPFLAGS_HAVE_FINALIZE
¶ Бит устанавливается, когда
tp_finalize
слот присутствует в структуре типа.Добавлено в версии 3.4.
Не рекомендуется, начиная с версии 3.8: Этот флаг больше не требуется, поскольку интерпретатор предполагает, что
tp_finalize
слот всегда присутствует в структуре типа.
-
_Py_TPFLAGS_HAVE_VECTORCALL
¶ Бит устанавливается, когда класс реализует протокол vectorcall. Дополнительные сведения см. в разделе
tp_vectorcall_offset
.Наследование:
Бит устанавливается для статических подтипов, если
tp_flags
не переопределен: подтип наследует_Py_TPFLAGS_HAVE_VECTORCALL
от своего базового типа, когдаtp_call
подтипаNULL
, аPy_TPFLAGS_HEAPTYPE
подтипа не задана.Типы кучи не наследуют
_Py_TPFLAGS_HAVE_VECTORCALL
.Примечание
Этот флаг является временным и, как ожидается, станет публичным в Python 3.9, с другим названием и, возможно, измененной семантикой. Если используется vectorcall, запланируйте обновление кода для Python 3.9.
Добавлено в версии 3.8.
-
-
const char*
PyTypeObject.tp_doc
¶ Необязательный указатель на строку C с окончанием NUL, предоставляющий докстринг для объекта этого типа. Он отображается в виде
__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
будет включать его.Предупреждение
При реализации
tp_traverse
необходимо посещать только те члены, которые владеет сущность (имея на них сильные ссылки). Для сущности, если объект поддерживает слабые ссылки через слотtp_weaklist
, указатель, поддерживающий связанный список (на что указывает tp_weaklist) не должен быть посещен, так как сущности напрямую не владеет слабыми ссылками на себя (список слабых ссылок предназначен для поддержки слабого эталонного механизма, но сущности не имеет сильной ссылки на элементы внутри него, поскольку они могут быть удалены, даже если сущности все еще живы).Обратите внимание, что
Py_VISIT()
требует, чтобы параметры visit и arglocal_traverse()
имели эти конкретные имена; не называйте их просто так.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC
,tp_traverse
,tp_clear
Это поле наследуется подтипами вместе с
tp_clear
и битом флагаPy_TPFLAGS_HAVE_GC
: бит флага,tp_traverse
иtp_clear
наследуются от базового типа, если все они равны нулю в подтипе.
-
inquiry
PyTypeObject.tp_clear
¶ Необязательный указатель на функцию очистки для сборщика мусора. Это используются только в том случае, если установлен бит флага
Py_TPFLAGS_HAVE_GC
. Сигнатура:int tp_clear(PyObject *);
Функция член
tp_clear
используются для разрывания ссылочных циклов в циклическом мусоре, обнаруженном сборщиком мусора. В совокупности всеtp_clear
функции в системе должны объединяться, чтобы разорвать все ссылочные циклы. Это тонко, и если есть сомнения обеспечитьtp_clear
функцию. Например, тип кортежа не реализует функциюtp_clear
, поскольку можно доказать, что ни один опорный цикл не может быть полностью составлен из кортежей. Поэтому функцииtp_clear
других типов должны быть достаточными для разрыва любого цикла, содержащего кортеж. Это не сразу очевидно, и редко есть веские причины, чтобы избежать реализацииtp_clear
.Реализации
tp_clear
должны удалить ссылки сущности на те его элементы, которые могут быть Python объектами, и установить его указатели на эти элементы, чтобыNULL
, как в следующем примере:static int local_clear(localobject *self) { Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }
Должен использоваться макрос
Py_CLEAR()
, поскольку очистка ссылок требует деликатности: ссылка на содержащийся объект не должна уменьшаться до тех пор, пока указатель на содержащийся объект не станетNULL
. Это связано с тем, что уменьшение количества ссылок может привести к тому, что содержащийся объект станет мусором, вызывая цепочку операций восстановления, которая может включать в себя вызов произвольного Python кода (из-за завершителей или колбэков слабых ссылок, связанных с содержащимся объектом). Если такой код может снова ссылаться на self, важно, чтобы указатель на содержащийся объект былNULL
в это время, чтобы self знал, что содержащийся объект больше не может быть использован. МакросPy_CLEAR()
выполняет операции в безопасном порядке.Поскольку цель функций
tp_clear
состоит в том, чтобы разорвать ссылочные циклы, нет необходимости очищать содержащиеся объекты, такие как строки Python или Python целые числа, которые не могут участвовать в ссылочных циклах. С другой стороны, может быть удобно очистить все содержащиеся Python объекты и записать функциюtp_dealloc
типа для вызоваtp_clear
.Более подробную информацию о Python схеме сбора мусора можно найти в разделе Поддержка циклической сборки мусора.
Наследование:
Группа:
Py_TPFLAGS_HAVE_GC
,tp_traverse
,tp_clear
Это поле наследуется подтипами вместе с
tp_traverse
и битом флагаPy_TPFLAGS_HAVE_GC
: бит флага,tp_traverse
иtp_clear
наследуются от базового типа, если все они равны нулю в подтипе.
-
richcmpfunc
PyTypeObject.tp_richcompare
¶ Необязательный указатель на богатую функцию сравнения, сигнатура которой -:
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
Первый параметр гарантированно является сущностью типа, который определяется
PyTypeObject
.Функция должна возвращать результатом сравнения (обычно
Py_True
илиPy_False
). Если сравнение не определено, оно должно возвращатьPy_NotImplemented
, если произошла другая ошибка, она должна возвращатьNULL
и задать условие исключения.Следующие константы определяются для использования в качестве третьего аргумента для
tp_richcompare
и дляPyObject_RichCompare()
:Константа Сравнение Py_LT
<
Py_LE
<=
Py_EQ
==
Py_NE
!=
Py_GT
>
Py_GE
>=
Следующий макрос определен для облегчения записи богатой функций сравнения:
-
Py_RETURN_RICHCOMPARE
(VAL_A, VAL_B, op)¶ Возвращает
Py_True
илиPy_False
из функции в зависимости от результата сравнения. VAL_A и VAL_B должны быть вызваны операторами сравнения C (например, это могут быть C ints или floats). Третий аргумент указывает запрошенную операцию, как дляPyObject_RichCompare()
.Счетчик ссылок возвращаемого значения правильно увеличивается.
При ошибке устанавливает исключение и возвращает
NULL
из функции.Добавлено в версии 3.7.
Наследование:
Группа:
tp_hash
,tp_richcompare
Это поле наследуется подтипами вместе с
tp_hash
: подтип наследуетtp_richcompare
иtp_hash
, когдаtp_richcompare
иtp_hash
подтипа являютсяNULL
.По умолчанию:
PyBaseObject_Type
обеспечиваетtp_richcompare
реализацию, которая может наследоваться. Однако если определено толькоtp_hash
, то даже унаследованная функция не используются и сущности типа не смогут участвовать в каких-либо сравнениях.-
-
Py_ssize_t
PyTypeObject.tp_weaklistoffset
¶ Если экземпляры этого типа слабо ссылаются, это поле больше нуля и содержит смещение в структуре экземпляра заголовка слабого списка ссылок (игнорируя заголовок GC, если он есть); это смещение используется функциями
PyObject_ClearWeakRefs()
иPyWeakref_*()
. Структура экземпляра должна включать поле типаPyObject*
, которое инициализировано какNULL
.Не путайте это поле с
tp_weaklist
; это заголовок списка для слабых ссылок на сам объект типа.Наследование:
Это поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить это смещение; это означает, что подтип использует заголовок списка слабых ссылок, отличный от базового типа. Так как заголовок списка всегда находится через
tp_weaklistoffset
, это не должно быть проблемой.Когда тип, определен инструкцией class, не имеет описания
__slots__
, и ни один из его базовых типов не является слабой ссылкой, этот тип становится слабо ссылочным путем добавления слота головы слабого списка ссылок к макету сущности и установкиtp_weaklistoffset
смещения этого слота.Когда объявление
__slots__
типа содержит слот с именем__weakref__
, этот слот становится головой списка слабых ссылок для сущности типа, и смещение слота сохраняется вtp_weaklistoffset
типа.Если объявление
__slots__
типа не содержит слот с именем__weakref__
, тип наследуетtp_weaklistoffset
от базового типа.
-
getiterfunc
PyTypeObject.tp_iter
¶ Необязательный указатель на функцию, которая возвращает итератор для объекта. Его наличие обычно сигнализирует о том, что сущности этого типа являются итерабельными (хотя последовательности могут быть итерабельны без этой функции).
Функция имеет ту же сигнатуру, что и
PyObject_GetIter()
:PyObject *tp_iter(PyObject *self);
Наследование:
Это поле наследуется подтипами.
-
iternextfunc
PyTypeObject.tp_iternext
¶ Необязательный указатель на функцию, которая возвращает следующий элемент итератора. Сигнатура:
PyObject *tp_iternext(PyObject *self);
Когда итератор исчерпан, он должен возвращать
NULL
; может быть установлено или не установленоStopIteration
исключение. При возникновении другой ошибки она также должна возвращатьNULL
. Его наличие сигнализирует, что сущности этого типа являются итераторами.Типы итератора также должны определять функцию
tp_iter
, и эта функция должна возвращать саму сущность итератора (не новую сущность итератора).Функция имеет те же сигнатуру, что и
PyIter_Next()
.Наследование:
Это поле наследуется подтипами.
-
struct PyMethodDef*
PyTypeObject.tp_methods
¶ Необязательный указатель на статический
NULL
-завершенный массивPyMethodDef
структур, объявляющий регулярные методы этого типа.Для каждого элемента массива в словарь типа добавляется элемент (см.
tp_dict
ниже), содержащая дескриптор метода.Наследование:
Это поле не наследуется подтипами (методы наследуются через другой механизм).
-
struct PyMemberDef*
PyTypeObject.tp_members
¶ Необязательный указатель на статический
NULL
-завершенный массивPyMemberDef
структур, объявляющий регулярные элементы данных (поля или слоты) сущности этого типа.Для каждой записи в массиве запись добавляется в словарь типа (см.
tp_dict
ниже), содержащая дескриптор-член.Наследование:
Это поле не наследуется подтипами (члены наследуются через другой механизм).
-
struct PyGetSetDef*
PyTypeObject.tp_getset
¶ Необязательный указатель на статический
NULL
-завершенный массивPyGetSetDef
структур, объявляющий вычисляемые атрибуты сущности этого типа.Для каждой записи в массиве запись добавляется в словарь типа (см.
tp_dict
ниже), содержащая дескриптор getset.Наследование:
Это поле не наследуется подтипами (вычисляемые атрибуты наследуются через другой механизм).
-
PyTypeObject*
PyTypeObject.tp_base
¶ Необязательный указатель на базовый тип, свойства которого наследуются. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа путем вызова метатипа.
Примечание
Инициализация слотов подчиняется правилам инициализации глобальных слотов. C99 требует, чтобы инициализаторы были «адресными константами». Обозначения функций, такие как
PyType_GenericNew()
, с неявным преобразованием в указатель являются допустимыми константами C99 адреса.Однако унарный оператор „&“, применяемый к нестатической переменной, подобной
PyBaseObject_Type()
, не требуется для создания адресной константы. Компиляторы могут поддерживать это (gcc поддерживает), MSVC поддерживает. Оба компилятора строго соответствуют стандарту в этом конкретном поведении.Следовательно,
tp_base
должны быть установлены в функции init модуля расширения.Наследование:
Это поле не наследуется подтипами (очевидно).
По умолчанию:
Это поле по умолчанию имеет значение
&PyBaseObject_Type
(которое для Python программистов называется типомobject
).
-
PyObject*
PyTypeObject.tp_dict
¶ Словарь типа хранится здесь по
PyType_Ready()
.Это поле обычно инициализируется для
NULL
перед вызовом PyType_Ready; он также может быть инициализирован в словаре, содержащий начальные атрибуты для типа. После инициализации типаPyType_Ready()
в этом словаре могут быть добавлены дополнительные атрибуты только в том случае, если они не соответствуют перегруженным операциям (например,__add__()
).Наследование:
Это поле не наследуется подтипами (хотя определенные здесь атрибуты наследуются через другой механизм).
По умолчанию:
Если это поле
NULL
,PyType_Ready()
назначает ему новый словарь.Предупреждение
Небезопасно использовать
PyDict_SetItem()
или иным образом изменятьtp_dict
с помощью словаря C-API.
-
descrgetfunc
PyTypeObject.tp_descr_get
¶ Необязательный указатель на функцию «get дескриптор».
Сигнатура функции:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
Наследование:
Это поле наследуется подтипами.
-
descrsetfunc
PyTypeObject.tp_descr_set
¶ Необязательный указатель на функцию для установки и удаления значения дескриптора.
Сигнатура функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Аргумент value имеет значение
NULL
для удаления значения.Наследование:
Это поле наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_dictoffset
¶ Если сущности этого типа содержат словарь, содержащий переменные сущности, это поле ненулевое и содержит смещение в сущности типа словаря переменных сущности; это смещение используются в
PyObject_GenericGetAttr()
.Не путайте это поле с
tp_dict
; это словарь для атрибуты самого объекта типа.Если значение этого поля больше нуля, оно определяет смещение от начала структуры сущности. Если значение меньше нуля, оно определяет смещение с конца структуры сущности. Отрицательное смещение дороже в использовании и должно быть используются только в том случае, если структура сущности содержит часть переменной длины. Это используются например, добавлением словаря переменной сущности к подтипам
str
илиtuple
. Обратите внимание, что в этом случае полеtp_basicsize
должно учитывать словарь, добавленный к концу, даже если словарь не включен в базовый формат объекта. В системе с размером указателя 4 байтаtp_dictoffset
следует установить на-4
, чтобы указать, что словарь находится в самом конце структуры.Действительное смещение словаря в сущности можно вычислить из отрицательного
tp_dictoffset
следующим образом:dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset if dictoffset is not aligned on sizeof(void*): round up to sizeof(void*)
где
tp_basicsize
,tp_itemsize
иtp_dictoffset
взяты из объекта типа, аob_size
взяты из сущности. Абсолютное значение принимается, поскольку для хранения знака числа в ints используется знакob_size
. (Никогда не нужно делать этот расчет самостоятельно; это делает для вас_PyObject_GetDictPtr()
.)Наследование:
Это поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить смещение; это означает, что подтип сущности хранит словарь со смещением, отличным от смещения базового типа. Поскольку словарь всегда находится через
tp_dictoffset
, это не должно быть проблемой.Если тип, определенный инструкцией class, не имеет объявления
__slots__
, и ни один из его базовых типов не имеет словаря сущности переменных, в макет сущности добавляется слот словаря, иtp_dictoffset
устанавливается в смещение этого слота.Если тип, определенный инструкцией class имеет объявление
__slots__
, он наследуетtp_dictoffset
от базового типа.(Добавление слота с именем
__dict__
в объявление__slots__
не приводит к ожидаемому эффекту, это просто вызывает путаницу. Может быть, это должно быть добавлено как функция так же, как__weakref__
.)По умолчанию:
Этот слот не имеет значения по умолчанию. Для статических типов, если поле является
NULL
,__dict__
не создается для сущности.
-
initproc
PyTypeObject.tp_init
¶ Необязательный указатель на функцию инициализации сущности.
Функция соответствует
__init__()
методу класса. Как и__init__()
, существует возможность создания сущности без вызова__init__()
, а также возможность повторной инициализации сущности путем повторного вызова метода__init__()
.Сигнатура функции:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
Аргумент self является инициализатором сущности; аргументы args и kwds представляют позиционные и ключевые аргументы вызова
__init__()
.Функция
tp_init
, если неNULL
, вызывается, когда сущности создается обычным образом путем вызова его типа после того, как функцияtp_new
типа возвращает сущность типа. Если функцияtp_new
возвращает сущность другого типа, который не является подтипом исходного типа, функцияtp_init
не вызывается; еслиtp_new
возвращает сущности подтипа исходного типа, вызываетсяtp_init
подтипа.Возвращает
0
при успехе,-1
и устанавливает исключение при ошибке.Наследование:
Это поле наследуется подтипами.
По умолчанию:
Для статических типов это поле не имеет значения по умолчанию.
-
allocfunc
PyTypeObject.tp_alloc
¶ Необязательный указатель на функцию аллокации сущности.
Сигнатура функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипы, созданные инструкцией class).
По умолчанию:
Для динамических подтипов в этом поле всегда устанавливается значение
PyType_GenericAlloc()
для принудительного применения стандартной стратегии распределения кучи.Для статических подтипов
PyBaseObject_Type
используетPyType_GenericAlloc()
. Это рекомендуемое значение для всех статически определенных типов.
-
newfunc
PyTypeObject.tp_new
¶ Необязательный указатель на функцию создания сущности.
Сигнатура функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент подтипа - это тип создаваемого объекта; аргументы args и kwds представляют позиционные и ключевые аргументы вызова типа. Обратите внимание, что подтип не должен совпадать с типом,
tp_new
функция которого вызывается; это может быть подтип этого типа (но не несвязанный тип).Функция
tp_new
должна вызыватьsubtype->tp_alloc(subtype, nitems)
, чтобы аллоцировать пространство для объекта, а затем выполнить только необходимую инициализацию. Инициализация, которую можно безопасно игнорировать или повторить, должна быть помещена вtp_init
обработчик. Хорошим правилом является то, что для неизменяемых типов вся инициализация должна происходить вtp_new
, в то время как для изменяемых типов большая часть инициализации должна быть отложена доtp_init
.Наследование:
Это поле наследуется подтипами, за исключением того, что оно не наследуется статическими типами,
tp_base
которых являетсяNULL
или&PyBaseObject_Type
.По умолчанию:
Для статических типов это поле не имеет значения по умолчанию. Это означает, что если позиция определена как
NULL
, тип не может быть вызван для создания новых сущностей; предположительно существует какой-то другой способ создания сущности, как фабричная функция.
-
freefunc
PyTypeObject.tp_free
¶ Необязательный указатель на функцию отмены аллокации сущности. Его сигнатура -:
void tp_free(void *self);
сигнатура инициализатор, совместимая с
PyObject_Free()
.Наследование:
Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипы, созданные инструкцией class)
По умолчанию:
В динамических подтипах в этом поле устанавливается деаллокатор, соответствующий
PyType_GenericAlloc()
и значение бита флагаPy_TPFLAGS_HAVE_GC
.Для статических подтипов
PyBaseObject_Type
использует PyObject_Del.
-
inquiry
PyTypeObject.tp_is_gc
¶ Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщик мусора должен знать, является ли конкретный объект коллектируемым или нет. Обычно достаточно посмотреть на
tp_flags
поле типа объекта и проверить бит флагаPy_TPFLAGS_HAVE_GC
. Но некоторые типы имеют смесь статически и динамически аллоцированных сущностей, а статически аллоцированные сущности не коллекционируются. Такие типы должны определять эту функцию; он должен возвращаеть1
для коллектируемой (collectible) сущности, а0
для сущности не подлежащей коллектированию (non-collectible). Сигнатура:int tp_is_gc(PyObject *self);
(Единственный пример - сами типы. Метатип,
PyType_Type
, определяет эту функцию, чтобы различать статически и динамически аллоцированные типы.)Наследование:
Это поле наследуется подтипами.
По умолчанию:
Этот слот не имеет значения по умолчанию. Если это поле
NULL
,Py_TPFLAGS_HAVE_GC
используются в качестве функционального эквивалента.
-
PyObject*
PyTypeObject.tp_bases
¶ Кортеж базовых типов.
Значение задается для типов, созданных инструкцией class. Оно должено быть
NULL
для статически определенных типов.Наследование:
Это поле не наследуется.
-
PyObject*
PyTypeObject.tp_mro
¶ Кортеж, содержащий расширенный набор базовых типов, начиная с самого типа и заканчивая
object
, в порядке разрешения метода.Наследование:
Это поле не наследуется; он рассчитывается свежим по
PyType_Ready()
.
-
PyObject*
PyTypeObject.tp_cache
¶ Неиспользуется. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
PyObject*
PyTypeObject.tp_subclasses
¶ Список слабых ссылок на подклассы. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
PyObject*
PyTypeObject.tp_weaklist
¶ Заголовок списка слабых ссылок для слабых ссылок на объект этого типа. Не унаследован. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
destructor
PyTypeObject.tp_del
¶ Это поле устарело. Вместо этого используйте
tp_finalize
.
-
unsigned int
PyTypeObject.tp_version_tag
¶ Используется для индексирования в кэше метода. Только для внутреннего использования.
Наследование:
Это поле не наследуется.
-
destructor
PyTypeObject.tp_finalize
¶ Необязательный указатель на функцию завершения сущности. Его сигнатура:
void tp_finalize(PyObject *self);
Если
tp_finalize
установлен, интерпретатор вызывает его один раз при завершении сущности. Вызывается либо из сборщика мусора (если сущности является частью изолированного ссылочного цикла), либо непосредственно перед удалением объекта. В любом случае, он гарантированно вызывается перед попыткой разорвать ссылочные циклы, гарантируя, что он находит объект в разумном состоянии.tp_finalize
не должен изменять текущий статус исключения; поэтому рекомендуется писать нетривиальный финализатор:static void local_finalize(PyObject *self) { PyObject *error_type, *error_value, *error_traceback; /* Сохранить текущее исключение, если оно есть. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); /* ... */ /* Восстановление сохраненного исключения. */ PyErr_Restore(error_type, error_value, error_traceback); }
Для учета этого поля (даже при наследовании) необходимо также установить бит флагов
Py_TPFLAGS_HAVE_FINALIZE
.Наследование:
Это поле наследуется подтипами.
Добавлено в версии 3.4.
См.также
«Безопасное завершение объекта» (PEP 442)
Остальные поля определяются только в том случае, если определен COUNT_ALLOCS
макроса теста функций, и предназначены только для внутреннего использования. Они
задокументированы здесь для полноты. None из этих полей наследуются
подтипами.
-
Py_ssize_t
PyTypeObject.tp_allocs
¶ Количество аллокаций.
-
Py_ssize_t
PyTypeObject.tp_frees
¶ Количество освобождений.
-
Py_ssize_t
PyTypeObject.tp_maxalloc
¶ Максимальное количество одновременно аллоцированных объектов.
-
PyTypeObject*
PyTypeObject.tp_prev
¶ Указатель на предыдущий объект типа с ненулевым полем
tp_allocs
.
-
PyTypeObject*
PyTypeObject.tp_next
¶ Указатель на объект следующего типа с ненулевым полем
tp_allocs
.
Кроме того, обратите внимание, что со сборкой мусора в Python, tp_dealloc
может вызываться от любого Python потока, не только из потока, который
создал объект (если объект становится частью refcount цикла, тот цикл мог бы
быть собран сборкой мусора в любом потоке). Это не проблема для Python
вызовов API, так как поток, на котором вызывается tp_dealloc, будет
владеть глобальной блокировкой интерпретатора (GIL). Однако, если уничтожаемый
объект в свою очередь уничтожает объекты из какой-либо другой библиотеки C или
C++, следует позаботиться о том, чтобы уничтожение тех объектов в потоке,
которые вызвали tp_dealloc, не нарушают никаких предположений библиотеки.
Типы кучи¶
Традиционно типы, определенные в C коде, являются статическими, то есть
статическая структура PyTypeObject
определяется непосредственно в коде и
инициализируется с помощью PyType_Ready()
.
Это приводит к типам, которые ограничены по отношению к типам, определенным в Python:
- Статические типы ограничены одним основанием, т.е. они не могут использовать множественное наследование.
- Объекты статического типа (но не обязательно их сущности) являются неизменяемыми. Невозможно добавить или изменить атрибуты объекта типа из Python.
- Объекты статического типа совместно используются в разных субинтерпретерах, поэтому они не должны включать состояние, специфичные для субинтерпретера.
Кроме того, поскольку PyTypeObject
не является частью стабильного ABI,
любые модули расширения, использующие статические типы, должны быть скомпилированы для
определенной Python минорной версии.
Альтернативой статическим типам является типы, размещенные в куче, или типы кучи
для краткости, которые тесно соответствуют классам, созданной Python
инструкцией class
.
Это делается путем заполнения структуры PyType_Spec
и вызова PyType_FromSpecWithBases()
.
Числовые структуры объектов¶
-
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
¶
-
inquiry
PyNumberMethods.nb_bool
¶
-
binaryfunc
PyNumberMethods.nb_lshift
¶
-
binaryfunc
PyNumberMethods.nb_rshift
¶
-
binaryfunc
PyNumberMethods.nb_and
¶
-
binaryfunc
PyNumberMethods.nb_xor
¶
-
binaryfunc
PyNumberMethods.nb_or
¶
-
void *
PyNumberMethods.nb_reserved
¶
-
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
¶
-
binaryfunc
PyNumberMethods.nb_matrix_multiply
¶
-
binaryfunc
PyNumberMethods.nb_inplace_matrix_multiply
¶
Сопоставление структур объектов¶
-
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()
,PyObject_SetSlice()
иPyObject_DelSlice()
. Она имеет ту же сигнатуру, что иPyObject_SetItem()
, но v также может задать значениеNULL
для удаления элемента. Если этот слотNULL
, объект не поддерживает назначение и удаление позиции.
Последовательность структур объектов¶
-
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
слот.
Буферные структуры объектов¶
-
PyBufferProcs
¶ Структура содержит указатели на функции, требующие буферные протоколы. Протокол определяет, как объект-экспортер может предоставлять свои внутренние данные объектам-потребителям.
-
getbufferproc
PyBufferProcs.bf_getbuffer
¶ Сигнатура этой функции:
int (PyObject *exporter, Py_buffer *view, int flags);
Обработка запроса на exporter для заполнения view в соответствии с указаниями flags. За исключением пункта (3), реализация этой функции ДОЛЖНА выполнить следующие шаги:
- Проверить, может ли запрос быть выполнен. Если нет, поднять
PyExc_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.
-
PyAsyncMethods
¶ Структура содержит указатели на функции, необходимые для реализации awaitable и асинхронный итератор объектов.
Вот определение структуры:
typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } PyAsyncMethods;
-
unaryfunc
PyAsyncMethods.am_await
¶ Сигнатура этой функции:
PyObject *am_await(PyObject *self);
Возвращаемый объект должен быть итератором, т.е.
PyIter_Check()
должен возвращать1
для него.Этот слот может иметь значение
NULL
, если объект не является awaitable.
-
unaryfunc
PyAsyncMethods.am_aiter
¶ Сигнатура этой функции:
PyObject *am_aiter(PyObject *self);
Должен возвращаться объектом awaitable. Дополнительные сведения см. в разделе
__anext__()
.Этот слот может иметь значение
NULL
, если объект не реализует протокол асинхронной итерации.
-
unaryfunc
PyAsyncMethods.am_anext
¶ Сигнатура этой функции:
PyObject *am_anext(PyObject *self);
Должна возвращать awaitable объект. Дополнительные сведения см. в разделе
__anext__()
. Для этого слота может быть установлено значениеNULL
.
Тип слота typedefs¶
-
PyObject *
(*allocfunc)
(PyTypeObject *cls, Py_ssize_t nitems)¶ Назначение этой функции состоит в том, чтобы отделить выделение памяти от инициализации памяти. Она должна возвращать указатель на блок памяти достаточной длины для сущности, соответствующим образом выровненный и инициализированный нулями, но с
ob_refcnt
, установлен в1
, иob_type
, установленным в аргумент типа. Если типаtp_itemsize
ненулевое, полеob_size
объекта должно быть инициализировано до nitems, а длина аллоцированный блока памяти должна бытьtp_basicsize + nitems*tp_itemsize
, округлена до кратногоsizeof(void*)
; в противном случае nitems не используются, и длина блока должна бытьtp_basicsize
.Функция не должна выполнять никакой другой сущности инициализации, даже для аллокации дополнительной памяти; это должно быть сделано
tp_new
.
-
PyObject *
(*vectorcallfunc)
(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶ Смотрите
tp_vectorcall_offset
.Аргументы для
vectorcallfunc
те же, что и для_PyObject_Vectorcall()
.Добавлено в версии 3.8.
-
PyObject *
(*getattrfunc)
(PyObject *self, char *attr)¶ Возвращает значение именованного атрибута для объекта.
-
int
(*setattrfunc)
(PyObject *self, char *attr, PyObject *value)¶ Задать значение именованного атрибута для объекта. Значение аргумента устанавливается в
NULL
для удаления атрибута.
-
PyObject *
(*getattrofunc)
(PyObject *self, PyObject *attr)¶ Возвращает значение именованного атрибута для объекта.
Смотрите
tp_getattro
.
-
int
(*setattrofunc)
(PyObject *self, PyObject *attr, PyObject *value)¶ Задать значение именованного атрибута для объекта. Значение аргумента устанавливается в
NULL
для удаления атрибутg.Смотрите
tp_setattro
.
-
PyObject *
(*richcmpfunc)
(PyObject *, PyObject *, int)¶ Смотрите
tp_richcompare
.
-
PyObject *
(*iternextfunc)
(PyObject *)¶ Смотрите
tp_iternext
.
Примеры¶
Ниже приведены простые примеры определений типов 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 = "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 */
"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;
PyObject *inst_dict;
PyObject *weakreflist;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = "My objects",
.tp_weaklistoffset = offsetof(MyObject, weakreflist),
.tp_dictoffset = offsetof(MyObject, inst_dict),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
.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, который не может быть разделен на подклассы и не может быть вызван для создания экземпляров (например, используя отдельную фабричную функцию):
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 = "my custom str",
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = NULL,
.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 *),
};