Тип объекты¶
Возможно, одна из самых важных структур объектной системы Python — это
структура, определяющая новый тип структуры — PyTypeObject
. Объекты
типа можно обрабатывать с помощью любой из функций PyObject_*()
или
PyType_*()
, но они не предлагают ничего интересного для большинства
приложений Python. У данных объектов фундаментальное значение для поведения
объектов, поэтому они очень важны для самого интерпретатора и для любого модуля
расширения, реализующего новые типы.
Тип объекты довольно большие по сравнению с большинством стандартных типов. Причина такого размера в том, что каждый объект типа хранит большое количество значений, в основном указатели функций C, каждое из которых реализует небольшую часть функциональности типа. Поля типового объекта подробно рассматриваются в данном разделе. Поля будут описаны в том порядке, в котором они встречаются в структуре.
В дополнение к следующему краткому справочнику раздел Примеры
предоставляет краткое представление о значении и использовании PyTypeObject
.
Краткий справочник¶
«слоты tp»¶
Если COUNT_ALLOCS
определена, то также существуют следующие поля
(только для внутреннего использования):
[1] | Имя слота в круглых скобках указывает на то, что оно (фактически) устарело.
Имена в угловых скобках следует рассматривать как доступные только для чтения.
Имена в квадратных скобках предназначены только для внутреннего пользования.
«<R>» (в качестве префикса) означает, что поле является обязательным (не должно быть NULL ). |
[2] | Колонки: «О»: установлен на «Т»: установлен на «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; /* Для печати в формате "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* Для распределения */
/* Способы реализации стандартных операций */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* ранее известный как tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Наборы методов для стандартных классов */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* Более стандартные операции (здесь для бинарной совместимости) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Функции для доступа к объекту как к буферу ввода/вывода */
PyBufferProcs *tp_as_buffer;
/* Флаги для определения наличия дополнительных/расширенных функций */
unsigned long tp_flags;
const char *tp_doc; /* Строка документации */
/* вызвать функцию для всех доступных объектов */
traverseproc tp_traverse;
/* удалить ссылки на содержащиеся объекты */
inquiry tp_clear;
/* богатые сравнения */
richcmpfunc tp_richcompare;
/* активатор слабой ссылки */
Py_ssize_t tp_weaklistoffset;
/* Итераторы */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Дескриптор атрибута и подклассы */
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; /* Процедура низкоуровневой свободной памяти */
inquiry tp_is_gc; /* Для PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* порядок разрешения метода */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;
/* Ввести тег версии кэша атрибута. Добавлено в версии 2.6 */
unsigned int tp_version_tag;
destructor tp_finalize;
} PyTypeObject;
Слоты PyObject¶
Структура объекта типа расширяет структуру PyVarObject
. Поле
ob_size
используется для динамических типов (создаётся
type_new()
, обычно вызывается из оператора класса). Обратите внимание,
что PyType_Type
(метатип) инициализирует
tp_itemsize
, что означает, что его экземпляры (т. е.
объекты типа) должны содержать поле ob_size
.
-
PyObject*
PyObject._ob_next
¶ -
PyObject *
PyObject._ob_prev
¶ Эти поля присутствуют только в том случае, если определён макрос
Py_TRACE_REFS
. Их инициализация вNULL
выполняется макросомPyObject_HEAD_INIT
. Для статически размещённых объектов эти поля всегда остаютсяNULL
. Для динамически выделяемых объектов эти два поля используются для связывания объекта с двусвязным списком всех живых объектов в куче. Это можно было использовать для различных целей отладки; в настоящее время единственное использование — это печать объектов, которые все ещё живы в конце прогона, когда установлена переменная средыPYTHONDUMPREFS
.Наследование:
Эти поля не наследуются подтипами.
-
Py_ssize_t
PyObject.ob_refcnt
¶ Это счётчик ссылок на объект типа, инициализированный как
1
макросомPyObject_HEAD_INIT
. Обратите внимание, что для статически распределённых объектов типа экземпляры типа (объекты, чейob_type
указывает обратно на тип), считаются не как ссылки. Но для динамически выделяемых типов объектов экземпляры считаются ссылками.Наследование:
Данное поле не наследуется подтипами.
-
PyTypeObject*
PyObject.ob_type
¶ Это тип типа, другими словами, его метатип. Оно инициализируется аргументом макроса
PyObject_HEAD_INIT
, и его значение обычно должно быть&PyType_Type
. Однако для динамически загружаемых модулей расширения, которые должны использоваться в Windows (по крайней мере), компилятор жалуется, что это недопустимый инициализатор. Поэтому принято передаватьNULL
в макросPyObject_HEAD_INIT
и явно инициализировать это поле в начале функции инициализации модуля, прежде чем делать что-либо ещё. Обычно это делается так:Foo_Type.ob_type = &PyType_Type;
Это должно быть сделано до создания любых экземпляров типа.
PyType_Ready()
проверяет, является лиob_type
NULL
, и если да, инициализирует его полемob_type
базового класса.PyType_Ready()
не изменит это поле, если оно не равно нулю.Наследование:
Данное поле наследуется подтипами.
Слоты PyVarObject¶
-
Py_ssize_t
PyVarObject.ob_size
¶ Для статически выделенных объектов типа это должно быть инициализировано нулём. Для динамически выделяемых типов объектов у этого поля особое внутреннее значение.
Наследование:
Данное поле не наследуется подтипами.
Слоты PyTypeObject¶
В каждом слоте есть раздел, определяющий наследование. Если
PyType_Ready()
может устанавливать значение, когда в поле установлено
значение NULL
, тогда также будет раздел «По умолчанию». (Обратите внимание,
что многие поля, установленные в PyBaseObject_Type
и
PyType_Type
, действуют как значения по умолчанию.)
-
const char*
PyTypeObject.tp_name
¶ Указатель на строку с завершающим нулем, содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна быть полным именем модуля, за которым следует точка, после неё следует имя типа; для встроенных типов это должно быть просто имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип с именем
T
, определённое в модулеM
в подпакетеQ
в пакетеP
, должно обладать инициализаторомtp_name
"P.Q.M.T"
.Для динамически выделяемых объектов типа это должно быть просто имя типа, а имя модуля, явно сохраненное в типе dict как значение для ключа
'__module__'
.Для статически выделенных объектов типа поле tp_name должно содержать точку. Все, что находится до последней точки, становится доступным как атрибут
__module__
, а всё, что находится после последней точки, становится доступным как атрибут__name__
.Если точка отсутствует, все поле
tp_name
становится доступным как атрибут__name__
, а атрибут__module__
не определён (если явно не установлен в словаре, как приведено выше). Это означает, что ваш тип невозможно запиклить. Кроме того, он не будет указан в документации модуля, созданной с помощью pydoc.Данное поле не должно быть
NULL
. Это единственное обязательное поле вPyTypeObject()
(кроме потенциальноtp_itemsize
).Наследование:
Данное поле не наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_basicsize
¶ -
Py_ssize_t
PyTypeObject.tp_itemsize
¶ Эти поля позволяют вычислять размер экземпляров типа в байтах.
Существует два типа типов: типы с экземплярами фиксированной длины содержат нулевое поле
tp_itemsize
, типы с экземплярами переменной длины содержат ненулевое полеtp_itemsize
. Для типа с экземплярами фиксированной длины у всех экземпляров одинаковый размер, указанный вtp_basicsize
.Для типа с экземплярами переменной длины у экземпляров должно быть поле
ob_size
, а размер экземпляра равенtp_basicsize
плюс N умноженное наtp_itemsize
, где N — «длина» объекта. Значение N обычно хранится в поле экземпляраob_size
. Есть исключения: например, целые числа используют отрицательное числоob_size
для обозначения отрицательного числа, а N — этоabs(ob_size)
. Кроме того, наличие поляob_size
в макете экземпляра не означает, что структура экземпляра переменной длины (например, у структуры для типа списка есть экземпляры фиксированной длины, но данные экземпляры содержат значимое полеob_size
).Базовый размер включает поля в экземпляре, объявленном макросом
PyObject_HEAD
илиPyObject_VAR_HEAD
(в зависимости от того, что используется для объявления структуры экземпляра), а это, в свою очередь, включает поля_ob_prev
и_ob_next
, если они присутствуют. Это означает, что единственный правильный способ получить инициализатор дляtp_basicsize
— использовать операторsizeof
в структуре, используемой для объявления макета экземпляра. Базовый размер не включает размер заголовка GC.Примечание о выравнивании: если элементы переменных требуют определенного выравнивания, об этом следует позаботиться с помощью значения
tp_basicsize
. Пример: предположим, что тип реализует массивdouble
.tp_itemsize
— этоsizeof(double)
. Программист несёт ответственность за то, чтобыtp_basicsize
было кратнымsizeof(double)
(при условии, что это требование выравнивания дляdouble
).Для любого типа с экземплярами переменной длины это поле не должно быть
NULL
.Наследование:
Эти поля наследуются по подтипам отдельно. Если у базового типа ненулевое значение
tp_itemsize
, обычно небезопасно устанавливать дляtp_itemsize
другое ненулевое значение в подтипе (хотя это зависит от реализации базового типа).
-
destructor
PyTypeObject.tp_dealloc
¶ Указатель на функцию деструктора экземпляра. Данная функция должна быть определена, если тип не гарантирует, что её экземпляры никогда не будут освобождены (как в случае синглтонов
None
иEllipsis
). Сигнатура функции:void tp_dealloc(PyObject *self);
Функция деструктора вызывается макросами
Py_DECREF()
иPy_XDECREF()
, когда новый счётчик ссылок равен нулю. На данный момент экземпляр все ещё существует, но ссылок на него нет. Функция деструктора должна освободить все ссылки, которыми владеет экземпляр, освободить все буферы памяти, принадлежащие экземпляру (с помощью функции освобождения, соответствующей функции выделения, используемой для выделения буфера), и вызвать функцию типаtp_free
. Если тип не является подтипом (нет установленного бита флагаPy_TPFLAGS_BASETYPE
), разрешается вызывать средство освобождения объекта напрямую, а не черезtp_free
. Освободитель объекта должен быть тем, который использовался для выделения экземпляра; Обычно этоPyObject_Del()
, если экземпляр был выделен с использованиемPyObject_New()
илиPyObject_VarNew()
, илиPyObject_GC_Del()
, если экземпляр был выделен с использованиемPyObject_GC_New()
илиPyObject_GC_NewVar()
.В завершении, если тип выделен в куче (
Py_TPFLAGS_HEAPTYPE
), освобождающий должен уменьшить счётчик ссылок для своего объекта типа после вызова освобождения типа. Чтобы избежать болтающихся указателей, рекомендуется использовать для этого:static void foo_dealloc(foo_object *self) { PyTypeObject *tp = Py_TYPE(self); // свободные ссылки и буферы здесь 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 с позиционными аргументами и ключевыми аргументами, указанными в кортеже и dict, соответственно.
Данная функция предназначена для использования в слоте
tp_call
. Она не возвращается кtp_call
и в настоящее время не проверяет флаг_Py_TPFLAGS_HAVE_VECTORCALL
. Чтобы вызвать объект, использовать вместо неё одну из функцийPyObject_Call
.
Примечание
Для типов кучи не рекомендуется реализовывать протокол vectorcall. Когда пользователь устанавливает
__call__
в коде Python, обновляется толькоtp_call
, что, возможно, делает его несовместимым с функцией vectorcall.Примечание
Семантика слота
tp_vectorcall_offset
является предварительной и ожидается, что она будет завершена в Python 3.9. Если вы используете vectorcall, запланировать обновление кода для Python 3.9.Изменено в версии 3.8: Данный слот использовался для форматирования печати в Python 2.x. В Python 3.0–3.7 он был зарезервирован и назван
tp_print
.Наследование:
Данное поле наследуется подтипами вместе с
tp_call
: подтип наследуетtp_vectorcall_offset
от своего базового типа, когдаtp_call
подтипа —NULL
.Обратите внимание, что типы кучи (включая подклассы, определённые в Python) не наследуют флаг
_Py_TPFLAGS_HAVE_VECTORCALL
.-
PyObject *
-
getattrfunc
PyTypeObject.tp_getattr
¶ Необязательный указатель на функцию get-attribute-string.
Данное поле устарело. Когда оно определено, оно должно указывать на функцию, которая действует так же, как функция
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);
Функция должна возвращать строку или Юникод объект. В идеале функция должна возвращать строку, которая при передаче в
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«ed, когда создается новый экземпляр, и DECREF»ed, когда экземпляр уничтожается (это не относится к экземплярам подтипы; только тип, на который ссылается экземпляр ob_type, получает INCREF«ed или DECREF»ed).Наследование:
???
-
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
.Наследование:
Данный бит устанавливается для static подтипа, если
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 и arg дляlocal_traverse()
имели эти имена; не называйте их просто так.Наследование:
Группа:
Py_TPFLAGS_HAVE_GC
,tp_traverse
,tp_clear
Данное поле наследуется подтипами вместе с
tp_clear
и битом флагаPy_TPFLAGS_HAVE_GC
: бит флага,tp_traverse
иtp_clear
наследуются от базового типа, если все они равны нулю в подтипе.
-
inquiry
PyTypeObject.tp_clear
¶ Необязательный указатель на функцию очистки для сборщика мусора. Используется только в том случае, если установлен бит флага
Py_TPFLAGS_HAVE_GC
. Сигнатура следующая:int tp_clear(PyObject *);
Функция-член
tp_clear
используется для прерывания ссылочных циклов в циклическом мусоре, обнаруженном сборщиком мусора. Взятые вместе, все функцииtp_clear
в системе должны объединиться, чтобы разорвать все ссылочные циклы. Это тонко, и если есть сомнения, предоставьте функциюtp_clear
. Например, тип кортежа не реализует функциюtp_clear
, потому что можно доказать, что ни один ссылочный цикл не может состоять полностью из кортежей. Следовательно, функцийtp_clear
других типов должно быть достаточно, чтобы прервать любой цикл, содержащий кортеж. Это не сразу очевидно, и редко есть веская причина избегать реализацииtp_clear
.Реализации
tp_clear
должны отбросить ссылки экземпляра на те из его членов, которые могут быть объектами Python, и установить его указатели на эти элементы наNULL
, как в следующем примере:static int local_clear(localobject *self) { Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }
Следует использовать макрос
Py_CLEAR()
, поскольку очистка ссылок является деликатным процессом: ссылка на содержащийся объект не должна уменьшаться до тех пор, пока указатель на содержащийся объект не будет установлен наNULL
. Это связано с тем, что уменьшение счётчика ссылок может привести к тому, что содержащийся объект станет мусором, запустив цепочку действий по восстановлению, которая может включать вызов произвольного кода Python (из-за финализаторов или обратных вызовов weakref, связанных с содержащимся объектом). Если такой код может снова ссылаться на self, важно, чтобы указатель на содержащийся объект был в это времяNULL
, чтобы self знал, что содержащийся объект больше не может использоваться. МакросPy_CLEAR()
выполняет операции в безопасном порядке.Поскольку цель функций
tp_clear
— разорвать ссылочные циклы, нет необходимости очищать содержащиеся объекты, такие как строки Python или целые числа Python, которые не могут участвовать в ссылочных циклах. С другой стороны, может быть удобно очистить все содержащиеся объекты Python и написать функцию типаtp_dealloc
для вызоваtp_clear
.Более подробную информацию о схеме сборки мусора Python можно найти в разделе Поддержка циклической сборки мусора.
Наследование:
Группа:
Py_TPFLAGS_HAVE_GC
,tp_traverse
,tp_clear
Данное поле наследуется подтипами вместе с
tp_traverse
и битом флагаPy_TPFLAGS_HAVE_GC
: бит флага,tp_traverse
иtp_clear
наследуются от базового типа, если они все равны нулю в подтипе.
-
richcmpfunc
PyTypeObject.tp_richcompare
¶ Необязательный указатель на функцию расширенного сравнения, сигнатура которой следующего вида:
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
Первый параметр гарантированно будет экземпляром типа, определенного
PyTypeObject
.Функция должна возвращать результат сравнения (обычно
Py_True
илиPy_False
). Если сравнение не определено, она должна возвращатьPy_NotImplemented
, если возникла другая ошибка, она должна возвращатьNULL
и установить условие исключения.Следующие константы определены для использования в качестве третьего аргумента для
tp_richcompare
иPyObject_RichCompare()
:Константа Сравнение Py_LT
<
Py_LE
<=
Py_EQ
==
Py_NE
!=
Py_GT
>
Py_GE
>=
Следующий макрос определён для упрощения написания расширенных функций сравнения:
-
Py_RETURN_RICHCOMPARE
(VAL_A, VAL_B, op)¶ Возвращает
Py_True
илиPy_False
из функции, в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочены операторами сравнения C (например, они могут быть целыми или плавающими в C). Третий аргумент указывает запрошенную операцию, как дляPyObject_RichCompare()
.Счётчик ссылок возвращаемого значения правильно увеличивается.
В случае ошибки устанавливает исключение и возвращает
NULL
из функции.Добавлено в версии 3.7.
Наследование:
Группа:
tp_hash
,tp_richcompare
Данное поле наследуется подтипами вместе с
tp_hash
: подтип наследуетtp_richcompare
иtp_hash
, когдаtp_richcompare
иtp_hash
подтипа оба являютсяNULL
.По умолчанию:
PyBaseObject_Type
предоставляет реализациюtp_richcompare
, которая может быть унаследована. Однако, если определён толькоtp_hash
, даже унаследованная функция не используется, и экземпляры типа не смогут участвовать ни в каких сравнениях.-
-
Py_ssize_t
PyTypeObject.tp_weaklistoffset
¶ Если экземпляры этого типа слабо ссылаются, это поле больше нуля и содержит смещение в структуре экземпляра заголовка списка слабых ссылок (игнорируя заголовок GC, если он есть); это смещение используется функциями
PyObject_ClearWeakRefs()
иPyWeakref_*()
. Структура экземпляра должна включать поле типаPyObject*
, которое инициализировано какNULL
.Не путайте это поле с
tp_weaklist
; это заголовок списка слабых ссылок на сам объект типа.Наследование:
Данное поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить это смещение; это означает, что подтип использует заголовок слабого списка ссылок, отличный от базового типа. Поскольку заголовок списка всегда находится через
tp_weaklistoffset
, это не должно быть проблемой.Когда тип, определённый оператором класса, не содержит объявления
__slots__
и ни у одного из его базовых типов нет слабой ссылки, на тип делается слабая ссылка путем добавления слота заголовка слабого списка ссылок в макет экземпляра и установкиtp_weaklistoffset
смещения этого слота.Когда объявление типа
__slots__
содержит слот с именем__weakref__
, данный слот становится заголовком слабого списка ссылок для экземпляров типа, а смещение слота сохраняется вtp_weaklistoffset
типа.Когда объявление типа
__slots__
не содержит слота с именем__weakref__
, тип наследует свойtp_weaklistoffset
от своего базового типа.
-
getiterfunc
PyTypeObject.tp_iter
¶ Необязательный указатель на функцию, возвращающую итератор для объекта. Его присутствие обычно сигнализирует о том, что экземпляры этого типа итерируемы (хотя последовательности могут быть итерируемыми без данной функции).
У данной функции та же сигнатура, что и у
PyObject_GetIter()
:PyObject *tp_iter(PyObject *self);
Наследование:
Данное поле наследуется подтипами.
-
iternextfunc
PyTypeObject.tp_iternext
¶ Необязательный указатель на функцию, которая возвращает следующий элемент в итераторе. Сигнатура:
PyObject *tp_iternext(PyObject *self);
Когда итератор исчерпан, он должен возвращать
NULL
; исключениеStopIteration
может быть установлено или не установлено. При возникновении другой ошибки он также должен возвращатьNULL
. Его наличие сигнализирует о том, что экземпляры этого типа являются итераторами.Типы итераторов также должны определять функцию
tp_iter
, и функция должна возвращать сам экземпляр итератора (а не новый экземпляр итератора).У данной функции та же сигнатура, что и у
PyIter_Next()
.Наследование:
Данное поле наследуется подтипами.
-
struct PyMethodDef*
PyTypeObject.tp_methods
¶ Необязательный указатель на статический массив с завершением
NULL
структурPyMethodDef
, объявляющий обычные методы данного типа.Для каждой записи в массиве в словарь типа добавляется запись (см.
tp_dict
ниже), содержащая дескриптор метода.Наследование:
Данное поле не наследуется подтипами (методы наследуются через другой механизм).
-
struct PyMemberDef*
PyTypeObject.tp_members
¶ Необязательный указатель на статический массив с завершением
NULL
структурPyMemberDef
, объявляющий обычные элементы данных (поля или слоты) экземпляров этого типа.Для каждой записи в массиве в словарь типа добавляется запись (см.
tp_dict
ниже), содержащая дескриптор члена.Наследование:
Данное поле не наследуется подтипами (члены наследуются через другой механизм).
-
struct PyGetSetDef*
PyTypeObject.tp_getset
¶ Необязательный указатель на статический завершающийся
NULL
массив структурPyGetSetDef
, объявляющий вычисляемые атрибуты экземпляров данного типа.Для каждой записи в массиве в словарь типа добавляется запись (см.
tp_dict
ниже), содержащая дескриптор getset.Наследование:
Данное поле не наследуется подтипами (вычисляемые атрибуты наследуются с помощью другого механизма).
-
PyTypeObject*
PyTypeObject.tp_base
¶ Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа путём вызова метатипа.
Примечание
Инициализация слота подчиняется правилам инициализации глобальных объектов. C99 требует, чтобы инициализаторы были «адресными константами». Обозначения функций, такие как
PyType_GenericNew()
, с неявным преобразованием в указатель, являются действительными адресными константами C99.Однако унарный оператор «&», применяемый к нестатической переменной, такой как
PyBaseObject_Type()
, не требуется для создания адресной константы. Компиляторы могут поддерживать это (gcc поддерживает), а MSVC — нет. Оба компилятора строго соответствуют стандарту в данном поведении.Следовательно,
tp_base
должен быть установлен в функции 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
¶ Необязательный указатель на функцию «получить дескриптор».
Сигнатура функции:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
Наследование:
Данное поле наследуется подтипами.
-
descrsetfunc
PyTypeObject.tp_descr_set
¶ Необязательный указатель на функцию для установки и удаления значения дескриптора.
Сигнатура функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Аргумент value устанавливается в
NULL
, чтобы удалить значение.Наследование:
Данное поле наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_dictoffset
¶ Если у экземпляров этого типа есть словарь, содержащий переменные экземпляра, данное поле не равно нулю и содержит смещение в экземплярах типа словаря переменных экземпляра; это смещение используется
PyObject_GenericGetAttr()
.Не путайте это поле с
tp_dict
; это словарь атрибутов самого объекта типа.Если значение этого поля больше нуля, оно определяет смещение от начала структуры экземпляра. Если значение меньше нуля, оно указывает смещение от конца структуры экземпляра. Отрицательное смещение дороже в использовании, и его следует использовать только тогда, когда структура экземпляра содержит часть переменной длины. Это используется, например, для добавления словаря переменных экземпляра к подтипам
str
илиtuple
. Обратите внимание, что полеtp_basicsize
должно учитывать словарь, добавляемый в конец в этом случае, даже если словарь не включён в базовый макет объекта. В системе с размером указателя 4 байта дляtp_dictoffset
следует установить значение-4
, чтобы указать, что словарь находится в самом конце структуры.Реальное смещение словаря в экземпляре может быть вычислено из отрицательного значения
tp_dictoffset
следующим образом:dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset if dictoffset is not aligned on sizeof(void*): round up to sizeof(void*)
где
tp_basicsize
,tp_itemsize
иtp_dictoffset
взяты из объекта типа, аob_size
взяты из экземпляра. Берётся абсолютное значение, потому что целые числа используют знакob_size
для хранения знака числа. (Нет необходимости производить данный расчёт самостоятельно; это сделает за вас_PyObject_GetDictPtr()
.)Наследование:
Данное поле наследуется подтипами, но см. правила, перечисленные ниже. Подтип может переопределить это смещение; это означает, что экземпляры подтипа хранят словарь с разницей в смещении, чем базовый тип. Поскольку словарь всегда находится через
tp_dictoffset
, это не должно быть проблемой.Когда у типа, определённого оператором класса, нет объявления
__slots__
и ни у одного из его базовых типов нет словаря переменных экземпляра, слот словаря добавляется в макет экземпляра, аtp_dictoffset
устанавливается на смещение этого слота.Когда у типа, определённого оператором класса, есть объявление
__slots__
, данный тип наследует свойtp_dictoffset
от своего базового типа.(Добавление слота с именем
__dict__
в объявление__slots__
не дает ожидаемого эффекта, это просто вызывает путаницу. Возможно, это следует добавить как функцию, такую же, как__weakref__
.)По умолчанию:
У данного слота нет значения по умолчанию. Для статических типов, если поле
NULL
, то для экземпляров не создаётся__dict__
.
-
initproc
PyTypeObject.tp_init
¶ Необязательный указатель на функцию инициализации экземпляра.
Данная функция соответствует методу классов
__init__()
. Как и__init__()
, можно создать экземпляр без вызова__init__()
, и можно повторно инициализировать экземпляр, снова вызвав его метод__init__()
.Сигнатура функции:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
Аргумент self — это инициализируемый экземпляр; аргументы args и kwds представляют позиционные аргументы и ключевые аргументы вызова
__init__()
.Функция
tp_init
, если неNULL
, вызывается, когда экземпляр создаётся обычным образом путём вызова его типа после того, как функция типаtp_new
вернула экземпляр типа. Если функцияtp_new
возвращает экземпляр какого-либо другого типа, который не является подтипом исходного типа, функцияtp_init
не вызывается; еслиtp_new
возвращает экземпляр подтипа исходного типа, вызываетсяtp_init
подтипа.Возвращает
0
в случае успеха,-1
и устанавливает исключение в случае ошибки.Наследование:
Данное поле наследуется подтипами.
По умолчанию:
Для статических типов у этого поля нет значения по умолчанию.
-
allocfunc
PyTypeObject.tp_alloc
¶ Необязательный указатель на функцию распределения экземпляров.
Сигнатура функции:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
Наследование:
Данное поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса).
По умолчанию:
Для динамических подтипов у этого поля всегда есть значение
PyType_GenericAlloc()
, чтобы использовать стандартную стратегию выделения кучи.Для статических подтипов
PyBaseObject_Type
используетPyType_GenericAlloc()
. Это рекомендуемое значение для всех статически определенных типов.
-
newfunc
PyTypeObject.tp_new
¶ Необязательный указатель на функцию создания экземпляра.
Сигнатура функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
Аргумент подтипа — это тип создаваемого объекта; аргументы args и kwds представляют позиционные аргументы и ключевые аргументы вызова типа. Обратите внимание, что подтип не обязательно должен совпадать с типом, для которого вызывается функция
tp_new
; это может быть подтип этого типа (но не несвязанный тип).Функция
tp_new
должна вызватьsubtype->tp_alloc(subtype, nitems)
, чтобы выделить место для объекта, а затем выполнить только необходимую дальнейшую инициализацию. Инициализацию, которую можно безопасно проигнорировать или повторить, следует поместить в обработчикtp_init
. Хорошее практическое правило состоит в том, что для неизменяемых типов вся инициализация должна происходить вtp_new
, в то время как для изменяемых типов большая часть инициализации должна быть отложена доtp_init
.Наследование:
Данное поле наследуется подтипами, за исключением того, что оно не наследуется статическими типами, у которых
tp_base
равноNULL
или&PyBaseObject_Type
.По умолчанию:
Для статических типов у этого поля нет значения по умолчанию. Это означает, что если слот определён как
NULL
, тип не может быть вызван для создания новых экземпляров; по-видимому, есть другой способ создания экземпляров, например фабричная функция.
-
freefunc
PyTypeObject.tp_free
¶ Необязательный указатель на функцию освобождения экземпляра. Его сигнатура:
void tp_free(void *self);
Инициализатор, совместимый с этой сигнатураю
PyObject_Free()
.Наследование:
Данное поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными оператором класса.)
По умолчанию:
В динамических подтипах это поле устанавливается на средство освобождения, подходящее для соответствия
PyType_GenericAlloc()
и значению бита флагаPy_TPFLAGS_HAVE_GC
.Для статических подтипов
PyBaseObject_Type
использует PyObject_Del.
-
inquiry
PyTypeObject.tp_is_gc
¶ Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщик мусора должен знать, можно ли собирать данный объект. Обычно достаточно посмотреть поле
tp_flags
типа объекта и проверить бит флагаPy_TPFLAGS_HAVE_GC
. Но у некоторых типов есть смесь статически и динамически выделенных экземпляров, и статически выделенные экземпляры не подлежат сбору. Такие типы должны определять эту функцию; он должен возвращать1
для коллекционного экземпляра и0
для не коллекционного экземпляра. Сигнатура:int tp_is_gc(PyObject *self);
(Единственным примером этого являются сами типы. Метатип,
PyType_Type
, определяет эту функцию, чтобы различать статически и динамически выделяемые типы.)Наследование:
Данное поле наследуется подтипами.
По умолчанию:
У данного слота нет значения по умолчанию. Если это поле
NULL
,Py_TPFLAGS_HAVE_GC
используется как функциональный эквивалент.
-
PyObject*
PyTypeObject.tp_bases
¶ Кортеж базовых типов.
Это установлено для типов, созданных оператором класса. Для статически определенных типов это должно быть
NULL
.Наследование:
Данное поле не наследуется.
-
PyObject*
PyTypeObject.tp_mro
¶ Кортеж, содержащий расширенный множество базовых типов, начиная с самого типа и заканчивая
object
, в порядке разрешения методов.Наследование:
Данное поле не наследуется; он рассчитан свежим методом
PyType_Ready()
.
-
PyObject*
PyTypeObject.tp_cache
¶ Не используется. Только для внутреннего пользования.
Наследование:
Данное поле не наследуется.
-
PyObject*
PyTypeObject.tp_subclasses
¶ Список слабых ссылок на подклассы. Только для внутреннего пользования.
Наследование:
Данное поле не наследуется.
-
PyObject*
PyTypeObject.tp_weaklist
¶ Слабый заголовок списка ссылок для слабых ссылок на объект этого типа. Не наследуется. Только для внутреннего пользования.
Наследование:
Данное поле не наследуется.
-
destructor
PyTypeObject.tp_del
¶ Данное поле устарело. Вместо него используйте
tp_finalize
.
-
unsigned int
PyTypeObject.tp_version_tag
¶ Используется для индексации в кеш-памяти методов. Только для внутреннего пользования.
Наследование:
Данное поле не наследуется.
-
destructor
PyTypeObject.tp_finalize
¶ Необязательный указатель на функцию завершения экземпляра. Его сигнатура:
void tp_finalize(PyObject *self);
Если установлен
tp_finalize
, интерпретатор вызывает его один раз при финализации экземпляра. Он вызывается либо из сборщика мусора (если экземпляр является частью изолированного ссылочного цикла), либо непосредственно перед освобождением объекта. В любом случае он гарантированно будет вызван перед попыткой разорвать циклы ссылок, гарантируя, что он найдет объект в нормальном состоянии.tp_finalize
не должен изменять текущий статус исключения; поэтому рекомендуемый способ написать нетривиальный финализатор:static void local_finalize(PyObject *self) { PyObject *error_type, *error_value, *error_traceback; /* Сохранить текущее исключение, если таковое имеется. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); /* ... */ /* Восстановление сохраненного исключения. */ PyErr_Restore(error_type, error_value, error_traceback); }
Чтобы это поле учитывалось (даже при наследовании), необходимо также установить бит флагов
Py_TPFLAGS_HAVE_FINALIZE
.Наследование:
Данное поле наследуется подтипами.
Добавлено в версии 3.4.
См.также
«Safe object finalization» (PEP 442)
Остальные поля определяются только в том случае, если определён макрос проверки
функций COUNT_ALLOCS
, и предназначены только для внутреннего
использования. Они задокументированы здесь для полноты. Ни одно из этих полей
не наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_allocs
¶ Количество размещений.
-
Py_ssize_t
PyTypeObject.tp_frees
¶ Количество фризов.
-
Py_ssize_t
PyTypeObject.tp_maxalloc
¶ Максимум одновременно размещаемых объектов.
-
PyTypeObject*
PyTypeObject.tp_prev
¶ Указатель на объект предыдущего типа с ненулевым полем
tp_allocs
.
-
PyTypeObject*
PyTypeObject.tp_next
¶ Указатель на объект следующего типа с ненулевым полем
tp_allocs
.
Также обратите внимание, что в Python со сборкой мусора
tp_dealloc
может быть вызван из любого потока Python,
а не только из потока, создавшего объект (если объект становится частью цикла
refcount, данный цикл может быть собран сборщиком мусора на любом потоке). Это не
проблема для вызовов Python API, поскольку поток, в котором вызывается
tp_dealloc, будет владеть глобальной блокировкой интерпретатора (GIL). Однако,
если уничтожаемый объект, в свою очередь, уничтожает объекты из какой-либо
другой библиотеки C или C++, следует позаботиться о том, чтобы уничтожение
этих объектов в потоке, вызванном tp_dealloc, не нарушило никаких предположений
библиотеки.
Типы кучи¶
Традиционно в коде C определены типы static, т. е. статическая структура
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
¶
-
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
¶ Данная структура содержит указатели на функции, необходимые для реализации ожидаемых объектов и асинхронный итератор.
Определение структуры:
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
, если объект не ожидаемый.
-
unaryfunc
PyAsyncMethods.am_aiter
¶ Сигнатура данной функции:
PyObject *am_aiter(PyObject *self);
Должен возвращать ожидаемый объект. Подробнее см.
__anext__()
.Данный слот может быть установлен в
NULL
, если объект не реализует протокол асинхронной итерации.
-
unaryfunc
PyAsyncMethods.am_anext
¶ Сигнатура данной функции:
PyObject *am_anext(PyObject *self);
Должна возвращать ожидаемый объект. Подробнее см.
__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
, чтобы удалить атрибут.См.
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 */
};
Тип, поддерживающий weakrefs, экземпляры dicts и хеширование:
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 *),
};