Объекты типов¶Type Objects
Пожалуй, одна из самых важных структур объектной системы Python – это структура, определяющая новый тип: структура PyTypeObject. Объекты типа можно обрабатывать с помощью любой из функций PyObject_*() или PyType_*(), но для большинства приложений Python они не представляют большого интереса. Эти объекты являются основой поведения объектов, поэтому они очень важны как для самого интерпретатора, так и для любых модулей расширения, реализующих новые типы.
Объекты типа довольно велики по сравнению с большинством стандартных типов. Причина такого размера в том, что каждый объект типа хранит большое количество значений, в основном указателей на функции C, каждый из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно рассматриваются в этом разделе. Поля будут описаны в порядке их появления в структуре.
Определения типов: unaryfunc, binaryfunc, ternaryfunc, inquiry, intargfunc, intintargfunc, intobjargproc, intintobjargproc, objobjargproc, destructor, freefunc, printfunc, getattrfunc, getattrofunc, setattrfunc, setattrofunc, reprfunc, hashfunc
Определение структуры для 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;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* ранее известный как tp_compare (Python 2)
или 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;
Структура объекта-типа расширяет структуру 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()не будет изменять это поле, если оно ненулевое.Это поле наследуется подтипами.
-
Py_ssize_t
PyVarObject.ob_size¶ Для статически выделенных объектов-типов это поле должно быть инициализировано нулём. Для динамически выделенных объектов-типов это поле имеет особый внутренний смысл.
Это поле не наследуется подтипами.
-
const char*
PyTypeObject.tp_name¶ Указатель на строку, завершающуюся NUL, содержащую имя типа. Для типов, доступных как глобальные переменные модуля, строка должна содержать полное имя модуля, за которым следует точка, а затем имя типа; для встроенных типов это должно быть просто имя типа. Если модуль является подмодулем пакета, полное имя пакета является частью полного имени модуля. Например, тип с именем
T, определённый в модулеMв подпакетеQпакетаP, должен иметь инициализаторtp_nameсо значением"P.Q.M.T".Для динамически выделенных объектов-типов это должно быть просто имя типа, а имя модуля явно хранится в словаре типа как значение для ключа
'__module__'.Для статически выделенных объектов-типов поле tp_name должно содержать точку. Всё до последней точки становится доступным как атрибут
__module__, а всё после последней точки – как атрибут__name__.Если точка отсутствует, всё поле
tp_nameстановится доступным как атрибут__name__, а атрибут__module__не определён (если только не задан явно в словаре, как описано выше). Это означает, что ваш тип невозможно будет сериализовать с помощью pickle. Кроме того, он не будет отображаться в документации модуля, создаваемой pydoc.Это поле не наследуется подтипами.
-
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_itemsize, обычно небезопасно устанавливатьtp_itemsizeв другое ненулевое значение в подтипе (хотя это зависит от реализации базового типа).Замечание о выравнивании: если переменные элементы требуют определённого выравнивания, это должно быть обеспечено значением
tp_basicsize. Пример: предположим, тип реализует массивdouble.tp_itemsizeравноsizeof(double). Программист должен гарантировать, чтоtp_basicsizeкратноsizeof(double)(при условии, что это и есть требование выравнивания дляdouble).
-
destructor
PyTypeObject.tp_dealloc¶ Указатель на функцию деструктора экземпляра. Эта функция должна быть определена, если только тип не гарантирует, что его экземпляры никогда не будут освобождены (как в случае с синглтонами
NoneиEllipsis).Функция деструктора вызывается макросами
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().Это поле наследуется подтипами.
-
printfunc
PyTypeObject.tp_print¶ Зарезервированный слот, ранее использовавшийся для форматирования вывода в Python 2.x.
-
getattrfunc
PyTypeObject.tp_getattr¶ Необязательный указатель на функцию получения строки атрибута.
Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_getattro, но принимает C-строку вместо объекта строки Python для указания имени атрибута. Сигнатура:PyObject * tp_getattr(PyObject *o, char *attr_name);
Это поле наследуется подтипами вместе с
tp_getattro: подтип наследует иtp_getattr, иtp_getattroот своего базового типа, когдаtp_getattrиtp_getattroподтипа оба равныNULL.
-
setattrfunc
PyTypeObject.tp_setattr¶ Необязательный указатель на функцию для установки и удаления атрибутов.
Это поле устарело. Если оно определено, оно должно указывать на функцию, которая действует так же, как функция
tp_setattro, но принимает C-строку вместо объекта строки Python для указания имени атрибута. Сигнатура:PyObject * tp_setattr(PyObject *o, char *attr_name, PyObject *v);
Аргумент v устанавливается в
NULLдля удаления атрибута. Это поле наследуется подтипами вместе сtp_setattro: подтип наследует какtp_setattr, так иtp_setattroот своего базового типа, еслиtp_setattrиtp_setattroподтипа оба равныNULL.
-
PyAsyncMethods*
tp_as_async¶ Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протоколы ожидаемого объекта и асинхронного итератора на уровне C. Подробнее см. в Структуры асинхронных объектов.
Новое в версии 3.5: Ранее было известно как
tp_compareиtp_reserved.
-
reprfunc
PyTypeObject.tp_repr¶ Необязательный указатель на функцию, реализующую встроенную функцию
repr().Сигнатура такая же, как для
PyObject_Repr(); она должна возвращать строку или объект Unicode. В идеале эта функция должна возвращать строку, которая при передаче вeval()в подходящем окружении возвращает объект с тем же значением. Если это невозможно, она должна возвращать строку, начинающуюся с'<'и заканчивающуюся'>', из которой можно вывести как тип, так и значение объекта.Если это поле не задано, возвращается строка вида
<%s object at %p>, где%sзаменяется именем типа, а%p– адресом памяти объекта.Это поле наследуется подтипами.
-
PyNumberMethods*
tp_as_number¶ Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих числовой протокол. Эти поля описаны в Структуры числовых объектов.
Поле
tp_as_numberне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
PySequenceMethods*
tp_as_sequence¶ Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протокол последовательности. Эти поля описаны в Структуры объектов-последовательностей.
Поле
tp_as_sequenceне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
PyMappingMethods*
tp_as_mapping¶ Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих протокол отображения. Эти поля описаны в Структуры объектов-отображений.
Поле
tp_as_mappingне наследуется, но содержащиеся в нём поля наследуются по отдельности.
-
hashfunc
PyTypeObject.tp_hash¶ Необязательный указатель на функцию, реализующую встроенную функцию
hash().Сигнатура такая же, как для
PyObject_Hash(); она должна возвращать значение типа Py_hash_t. Значение-1не должно возвращаться как обычное возвращаемое значение; при возникновении ошибки во время вычисления хеша функция должна установить исключение и вернуть-1.Это поле можно явно установить в
PyObject_HashNotImplemented(), чтобы заблокировать наследование хеш-метода от родительского типа. Это интерпретируется как эквивалент__hash__ = Noneна уровне Python, в результате чегоisinstance(o, collections.Hashable)корректно возвращаетFalse. Обратите внимание, что верно и обратное: установка__hash__ = Noneв классе на уровне Python приведет к тому, что слотtp_hashбудет установлен вPyObject_HashNotImplemented().Когда это поле не установлено, попытка получить хеш объекта вызывает
TypeError.Это поле наследуется подтипами вместе с
tp_richcompare: подтип наследует какtp_richcompare, так иtp_hash, еслиtp_richcompareиtp_hashподтипа равныNULL.
-
ternaryfunc
PyTypeObject.tp_call¶ Необязательный указатель на функцию, реализующую вызов объекта. Должен быть
NULL, если объект не вызываем. Сигнатура такая же, как дляPyObject_Call().Это поле наследуется подтипами.
-
reprfunc
PyTypeObject.tp_str¶ Необязательный указатель на функцию, реализующую встроенную операцию
str(). (Обратите внимание, чтоstrтеперь является типом, аstr()вызывает конструктор этого типа. Этот конструктор вызываетPyObject_Str()для выполнения фактической работы, иPyObject_Str()будет вызывать этот обработчик.)Сигнатура такая же, как у
PyObject_Str(); она должна возвращать строку или объект Unicode. Эта функция должна возвращать «дружественное» строковое представление объекта, поскольку именно это представление будет использоваться, в частности, функциейprint().Если это поле не задано, вызывается
PyObject_Repr()для возврата строкового представления.Это поле наследуется подтипами.
-
getattrofunc
PyTypeObject.tp_getattro¶ Необязательный указатель на функцию получения атрибута.
Сигнатура такая же, как у
PyObject_GetAttr(). Обычно удобно устанавливать это поле вPyObject_GenericGetAttr(), которое реализует обычный способ поиска атрибутов объекта.Это поле наследуется подтипами вместе с
tp_getattr: подтип наследует иtp_getattr, иtp_getattroот своего базового типа, когдаtp_getattrиtp_getattroподтипа оба равныNULL.
-
setattrofunc
PyTypeObject.tp_setattro¶ Необязательный указатель на функцию для установки и удаления атрибутов.
Сигнатура такая же, как у
PyObject_SetAttr(), но необходимо поддерживать установку v вNULLдля удаления атрибута. Обычно удобно устанавливать это поле вPyObject_GenericSetAttr(), которое реализует обычный способ установки атрибутов объекта.Это поле наследуется подтипами вместе с
tp_setattr: подтип наследует иtp_setattr, иtp_setattroот своего базового типа, когдаtp_setattrиtp_setattroподтипа оба равныNULL.
-
PyBufferProcs*
PyTypeObject.tp_as_buffer¶ Указатель на дополнительную структуру, содержащую поля, значимые только для объектов, реализующих буферный интерфейс. Эти поля описаны в Buffer Object Structures.
Поле
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.В настоящее время определены следующие битовые маски; их можно объединять с помощью оператора
|для получения значения поляtp_flags. МакросPyType_HasFeature()принимает тип и значение флагов, tp и f, и проверяет, является лиtp->tp_flags & fненулевым.-
Py_TPFLAGS_HEAPTYPE¶ Этот бит устанавливается, когда сам объект типа выделяется в куче. В таком случае поле
ob_typeего экземпляров считается ссылкой на тип, и счётчик ссылок объекта типа увеличивается (INCREF) при создании нового экземпляра и уменьшается (DECREF) при уничтожении экземпляра (это не относится к экземплярам подтипов; только тип, на который ссылается 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(). Дополнительная информация – в разделе Поддержка циклической сборки мусора. Этот бит также означает, что связанные со сборкой мусора поляtp_traverseиtp_clearприсутствуют в объекте типа.
-
Py_TPFLAGS_DEFAULT¶ Это битовая маска всех битов, относящихся к наличию определённых полей в объекте типа и его структурах расширения. В настоящее время она включает следующие биты:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION,Py_TPFLAGS_HAVE_VERSION_TAG.
-
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.
-
-
const char*
PyTypeObject.tp_doc¶ Необязательный указатель на C-строку, завершающуюся нулевым символом, содержащую строку документации для этого объекта типа. Это отображается как атрибут
__doc__у типа и его экземпляров.Это поле не наследуется подтипами.
-
traverseproc
PyTypeObject.tp_traverse¶ Необязательный указатель на функцию обхода для сборщика мусора. Используется только если установлен флаг
Py_TPFLAGS_HAVE_GC. Дополнительную информацию о схеме сборки мусора 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()имели именно такие имена; не следует называть их как попало.Это поле наследуется подтипами вместе с
tp_clearи флагомPy_TPFLAGS_HAVE_GC: флаг,tp_traverseиtp_clearнаследуются от базового типа, если они равны нулю в подтипе.
-
inquiry
PyTypeObject.tp_clear¶ Необязательный указатель на функцию очистки для сборщика мусора. Используется только если установлен флаг
Py_TPFLAGS_HAVE_GC.Функция-член
tp_clearиспользуется для разрыва циклических ссылок в циклическом мусоре, обнаруженном сборщиком мусора. В совокупности все функцииtp_clearв системе должны совместно разрывать все циклические ссылки. Это тонкий момент, и при любых сомнениях следует предоставить функциюtp_clear. Например, тип tuple не реализует функцию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 можно найти в разделе Поддержка циклической сборки мусора.
Это поле наследуется подтипами вместе с
tp_traverseи флагомPy_TPFLAGS_HAVE_GC: флаг,tp_traverseиtp_clearнаследуются от базового типа, если они равны нулю в подтипе.
-
richcmpfunc
PyTypeObject.tp_richcompare¶ Необязательный указатель на функцию расширенного сравнения, сигнатура которой
PyObject *tp_richcompare(PyObject *a, PyObject *b, int op). Первый параметр гарантированно является экземпляром типа, определённогоPyTypeObject.Функция должна возвращать результат сравнения (обычно
Py_TrueилиPy_False). Если сравнение не определено, она должна вернутьPy_NotImplemented; если произошла другая ошибка, она должна вернутьNULLи установить условие исключения.Примечание
Если требуется реализовать тип, для которого имеет смысл только ограниченный набор сравнений (например,
==и!=, но не<и др.), следует напрямую возбуждатьTypeErrorв функции расширенного сравнения.Это поле наследуется подтипами вместе с
tp_hash: подтип наследуетtp_richcompareиtp_hash, когдаtp_richcompareиtp_hashподтипа обаNULL.Следующие константы определены для использования в качестве третьего аргумента для
tp_richcompareи дляPyObject_RichCompare():Константа
Сравнение
Py_LT<Py_LE<=Py_EQ==Py_NE!=Py_GT>Py_GE>=Для упрощения написания функций расширенного сравнения определён следующий макрос:
-
PyObject *
Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, int op)¶ Возвращает
Py_TrueилиPy_Falseиз функции в зависимости от результата сравнения. VAL_A и VAL_B должны быть упорядочиваемыми с помощью операторов сравнения языка C (например, это могут быть значения типа int или float). Третий аргумент задаёт требуемую операцию, как и дляPyObject_RichCompare().Счётчик ссылок возвращаемого значения корректно увеличивается.
В случае ошибки устанавливает исключение и возвращает NULL из функции.
Добавлено в версии 3.7.
-
PyObject *
-
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().Это поле наследуется подтипами.
-
iternextfunc
PyTypeObject.tp_iternext¶ Необязательный указатель на функцию, возвращающую следующий элемент итератора. Когда итератор исчерпан, она должна вернуть
NULL; при этом исключениеStopIterationможет быть установлено, а может и нет. При возникновении другой ошибки она также должна вернутьNULL. Наличие этой функции указывает на то, что экземпляры данного типа являются итераторами.Типы-итераторы также должны определять функцию
tp_iter, и эта функция должна возвращать сам экземпляр итератора (не новый экземпляр итератора).Эта функция имеет ту же сигнатуру, что и
PyIter_Next().Это поле наследуется подтипами.
-
struct PyMethodDef*
PyTypeObject.tp_methods¶ Необязательный указатель на статический массив структур
PyMethodDef, завершающийсяNULL, объявляющий обычные методы этого типа.Для каждой записи в массиве в словарь типа добавляется запись (см.
tp_dictниже), содержащая дескриптор метода.Это поле не наследуется подтипами (методы наследуются через другой механизм).
-
struct PyMemberDef*
PyTypeObject.tp_members¶ Необязательный указатель на статический массив
PyMemberDefструктур, завершающийсяNULL, объявляющий обычные элементы данных (поля или слоты) экземпляров этого типа.Для каждой записи в массиве в словарь типа добавляется запись, содержащая дескриптор члена (см.
tp_dictниже).Это поле не наследуется подтипами (члены наследуются через другой механизм).
-
struct PyGetSetDef*
PyTypeObject.tp_getset¶ Необязательный указатель на статический массив
PyGetSetDefструктур, завершающийсяNULL, объявляющий вычисляемые атрибуты экземпляров этого типа.Для каждой записи в массиве в словарь типа добавляется запись, содержащая дескриптор getset (см.
tp_dictниже).Это поле не наследуется подтипами (вычисляемые атрибуты наследуются через другой механизм).
-
PyTypeObject*
PyTypeObject.tp_base¶ Необязательный указатель на базовый тип, от которого наследуются свойства типа. На этом уровне поддерживается только одиночное наследование; множественное наследование требует динамического создания объекта типа вызовом метатипа.
Это поле не наследуется подтипами (очевидно), но по умолчанию оно равно
&PyBaseObject_Type(которое программистам Python известно как типobject).
-
PyObject*
PyTypeObject.tp_dict¶ Словарь типа сохраняется здесь с помощью
PyType_Ready().Это поле обычно должно быть инициализировано значением
NULLдо вызова PyType_Ready; его также можно инициализировать словарём с начальными атрибутами типа. После того, какPyType_Ready()инициализирует тип, дополнительные атрибуты можно добавлять в этот словарь только если они не соответствуют перегруженным операциям (например,__add__()).Это поле не наследуется подтипами (хотя определённые здесь атрибуты наследуются через другой механизм).
Предупреждение
Небезопасно использовать
PyDict_SetItem()на или иным образом изменятьtp_dictс помощью C-API словаря.
-
descrgetfunc
PyTypeObject.tp_descr_get¶ Необязательный указатель на функцию «descriptor 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);
Аргумент значение устанавливается в
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, это не должно вызывать проблем.Если тип, определённый с помощью оператора class, не содержит объявления
__slots__, и ни один из его базовых типов не имеет словаря переменных экземпляра, в компоновку экземпляра добавляется слот словаря, аtp_dictoffsetустанавливается на смещение этого слота.Если тип, определённый с помощью оператора class, содержит объявление
__slots__, тот тип наследует значениеtp_dictoffsetот своего базового типа.(Добавление слота с именем
__dict__в объявление__slots__не даёт ожидаемого эффекта, а только вызывает путаницу. Возможно, эту возможность стоит добавить как отдельную функцию, подобно__weakref__.)
-
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подтипа.Это поле наследуется подтипами.
-
allocfunc
PyTypeObject.tp_alloc¶ Необязательный указатель на функцию выделения экземпляра.
Сигнатура функции:
PyObject *tp_alloc(PyTypeObject *self, 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.Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными выражением class); в последних это поле всегда устанавливается в
PyType_GenericAlloc(), чтобы принудительно использовать стандартную стратегию выделения в куче. Это также рекомендуемое значение для статически определённых типов.
-
newfunc
PyTypeObject.tp_new¶ Необязательный указатель на функцию создания экземпляра.
Если для данного типа эта функция равна
NULL, то такой тип нельзя вызвать для создания новых экземпляров; предполагается, что существует другой способ создания экземпляров, например, фабричная функция.Сигнатура функции:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
Аргумент subtype – это тип создаваемого объекта; аргументы args и kwds представляют позиционные и именованные аргументы вызова типа. Обратите внимание, что subtype не обязан совпадать с типом, для которого вызывается функция
tp_new; это может быть подтип этого типа (но не произвольный тип).Функция
tp_newдолжна вызыватьsubtype->tp_alloc(subtype, nitems)для выделения памяти под объект, а затем выполнять лишь минимально необходимую инициализацию. Инициализацию, которую можно безопасно пропустить или повторить, следует помещать в обработчикtp_init. Хорошее эмпирическое правило: для неизменяемых типов вся инициализация должна выполняться вtp_new, а для изменяемых типов большую часть инициализации лучше отложить доtp_init.Это поле наследуется подтипами, за исключением статических типов, у которых
tp_baseравноNULLили&PyBaseObject_Type.
-
destructor
PyTypeObject.tp_free¶ Необязательный указатель на функцию освобождения экземпляра. Её сигнатура:
freefunc:void tp_free(void *)
Инициализатор, совместимый с этой сигнатурой:
PyObject_Free().Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными выражением class); в последних это поле устанавливается в освободитель, подходящий для
PyType_GenericAlloc()и значения бита флагаPy_TPFLAGS_HAVE_GC.
-
inquiry
PyTypeObject.tp_is_gc¶ Необязательный указатель на функцию, вызываемую сборщиком мусора.
Сборщику мусора необходимо знать, подлежит ли данный объект сборке или нет. Обычно достаточно посмотреть на поле
tp_flagsтипа объекта и проверить бит флагаPy_TPFLAGS_HAVE_GC. Но некоторые типы имеют смесь статически и динамически выделенных экземпляров, причём статически выделенные экземпляры не подлежат сборке. Таким типам следует определить эту функцию; она должна возвращать1для собираемого экземпляра и0для несобираемого. Сигнатура:int tp_is_gc(PyObject *self)
(Единственный пример этого – сами типы. Метатип,
PyType_Type, определяет эту функцию, чтобы различать статически и динамически выделенные типы.)Это поле наследуется подтипами.
-
PyObject*
PyTypeObject.tp_bases¶ Кортеж базовых типов.
Это устанавливается для типов, созданных с помощью оператора class. Для статически определённых типов это должно быть
NULL.Это поле не наследуется.
-
PyObject*
PyTypeObject.tp_mro¶ Кортеж, содержащий расширенный набор базовых типов, начиная с самого типа и заканчивая
object, в порядке разрешения методов (MRO).Это поле не наследуется; оно вычисляется заново с помощью
PyType_Ready().
-
destructor
PyTypeObject.tp_finalize¶ Необязательный указатель на функцию финализации экземпляра. Её сигнатура:
destructor:void tp_finalize(PyObject *)
Если
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)
-
PyObject*
PyTypeObject.tp_cache¶ Не используется. Не наследуется. Только для внутреннего использования.
-
PyObject*
PyTypeObject.tp_subclasses¶ Список слабых ссылок на подклассы. Не наследуется. Только для внутреннего использования.
-
PyObject*
PyTypeObject.tp_weaklist¶ Голова списка слабых ссылок для слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего использования.
Остальные поля определены только в том случае, если определён макрос проверки функциональности COUNT_ALLOCS, и предназначены исключительно для внутреннего использования. Они описаны здесь для полноты. Ни одно из этих полей не наследуется подтипами.
-
Py_ssize_t
PyTypeObject.tp_allocs¶ Количество выделений памяти.
-
Py_ssize_t
PyTypeObject.tp_frees¶ Количество освобождений.
-
Py_ssize_t
PyTypeObject.tp_maxalloc¶ Максимальное количество одновременно выделенных объектов.
-
PyTypeObject*
PyTypeObject.tp_next¶ Указатель на следующий объект типа с ненулевым полем
tp_allocs.
Также следует отметить, что в Python со сборкой мусора tp_dealloc может вызываться из любого потока Python, а не только из того, который создал объект (если объект становится частью цикла подсчёта ссылок, этот цикл может быть собран сборщиком мусора в любом потоке). Это не проблема для вызовов Python API, поскольку поток, в котором вызывается tp_dealloc, будет владеть глобальной блокировкой интерпретатора (GIL). Однако, если уничтожаемый объект, в свою очередь, уничтожает объекты из какой-либо другой библиотеки C или C++, следует соблюдать осторожность, чтобы убедиться, что уничтожение этих объектов в потоке, вызвавшем tp_dealloc, не нарушит никаких предположений библиотеки.
Структуры числовых объектов¶Number Object Structures
-
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.
Структуры объектов отображения¶Mapping Object Structures
-
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, объект не поддерживает присваивание и удаление элементов.
Структуры объектов последовательностей¶Sequence Object Structures
-
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\nзаполнен, он вызывается, и длина последовательности используется для вычисления положительного\nиндекса, который передаётся вsq_item. Еслиsq_lengthравноNULL,\nиндекс передаётся функции как есть.
-
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.
Структуры объектов буфера¶Buffer Object Structures
-
PyBufferProcs¶ Эта структура содержит указатели на функции, необходимые для протокола буфера. Протокол определяет, как объект-экспортёр может предоставлять свои внутренние данные объектам-потребителям.
-
getbufferproc
PyBufferProcs.bf_getbuffer¶ Сигнатура этой функции:
int (PyObject *exporter, Py_buffer *view, int flags);
Обрабатывает запрос к экспортёру на заполнение представления в соответствии с флагами. За исключением пункта (3), реализация этой функции ОБЯЗАНА выполнить следующие шаги:
Проверить, можно ли удовлетворить запрос. Если нет, возбудить
PyExc_BufferError, установитьview->objвNULLи вернуть-1.Заполнить запрошенные поля.
Увеличить внутренний счётчик числа экспортов.
Установить
view->objв экспортёр и увеличитьview->obj.Вернуть
0.
Если экспортёр является частью цепочки или дерева поставщиков буферов, можно использовать две основные схемы:
Повторный экспорт: каждый элемент дерева выступает в роли экспортирующего объекта и устанавливает
view->objв новую ссылку на себя.Перенаправление: запрос буфера перенаправляется корневому объекту дерева. Здесь
view->objбудет новой ссылкой на корневой объект.
Отдельные поля представления описаны в разделе Структура буфера, правила, как экспортёр должен реагировать на конкретные запросы – в разделе Типы запросов буфера.
Вся память, на которую указывает структура
Py_buffer, принадлежит экспортёру и должна оставаться действительной, пока есть хотя бы один потребитель.format,shape,strides,suboffsetsиinternalдоступны потребителю только для чтения.PyBuffer_FillInfo()предоставляет простой способ предоставления простого байтового буфера, корректно обрабатывая все типы запросов.PyObject_GetBuffer()– это интерфейс для потребителя, который оборачивает эту функцию.
-
releasebufferproc
PyBufferProcs.bf_releasebuffer¶ Сигнатура этой функции:
void (PyObject *exporter, Py_buffer *view);
Обрабатывает запрос на освобождение ресурсов буфера. Если никакие ресурсы освобождать не нужно,
PyBufferProcs.bf_releasebufferможет бытьNULL. В противном случае стандартная реализация этой функции выполнит следующие необязательные шаги:Уменьшить внутренний счётчик числа экспортов.
Если счётчик равен
0, освободить всю память, связанную с представлением.
Экспортёр ОБЯЗАН использовать поле
internalдля отслеживания ресурсов, специфичных для буфера. Гарантируется, что это поле остаётся постоянным, в то время как потребитель МОЖЕТ передавать копию исходного буфера в качестве аргумента view.Эта функция НЕ ДОЛЖНА уменьшать
view->obj, так как это делается автоматически вPyBuffer_Release()(такая схема полезна для разрыва циклических ссылок).PyBuffer_Release()– это интерфейс для потребителя, который оборачивает эту функцию.
Асинхронные структуры объектов¶Async Object Structures
Новое в версии 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.