Документация Python неофициальный перевод

Объекты типовType Objects

Пожалуй, одна из самых важных структур объектной системы Python – это структура, определяющая новый тип: структура PyTypeObject. Объекты типа можно обрабатывать с помощью любой из функций PyObject_*() или PyType_*(), но для большинства приложений Python они не представляют большого интереса. Эти объекты являются основой поведения объектов, поэтому они очень важны как для самого интерпретатора, так и для любых модулей расширения, реализующих новые типы.

Объекты типа довольно велики по сравнению с большинством стандартных типов. Причина такого размера в том, что каждый объект типа хранит большое количество значений, в основном указателей на функции C, каждый из которых реализует небольшую часть функциональности типа. Поля объекта типа подробно рассматриваются в этом разделе. Поля будут описаны в порядке их появления в структуре.

Определения типов: unaryfunc, binaryfunc, ternaryfunc, inquiry, coercion, intargfunc, intintargfunc, intobjargproc, intintobjargproc, objobjargproc, destructor, freefunc, printfunc, getattrfunc, getattrofunc, setattrfunc, setattrofunc, cmpfunc, reprfunc, hashfunc

Определение структуры для PyTypeObject можно найти в Include/object.h. Для удобства здесь повторяется определение, приведённое там:

typedef struct _typeobject {
    PyObject_VAR_HEAD
    char *tp_name; /* Для вывода в формате "<module>.<name>" */
    int tp_basicsize, tp_itemsize; /* Для выделения памяти */

    /* Методы для реализации стандартных операций */

    destructor tp_dealloc;
    printfunc tp_print;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    cmpfunc tp_compare;
    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;

    /* Флаги для определения наличия опциональных/расширенных возможностей */
    long tp_flags;

    char *tp_doc; /* Строка документации */

    /* Назначенное значение в версии 2.0 */
    /* вызов функции для всех доступных объектов */
    traverseproc tp_traverse;

    /* удаление ссылок на содержащиеся объекты */
    inquiry tp_clear;

    /* Назначенное значение в версии 2.1 */
    /* расширенные сравнения */
    richcmpfunc tp_richcompare;

    /* включение слабых ссылок */
    long tp_weaklistoffset;

    /* Добавлено в версии 2.2 */
    /* Итераторы */
    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;
    long 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;

} 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 указывает обратно на тип) не считаются ссылками. Но для динамически выделенных объектов-типов экземпляры считаются ссылками.

Это поле не наследуется подтипами.

Изменено в версии 2.5: Ранее это поле имело тип int. Это может потребовать изменений в коде для корректной поддержки 64-битных систем.

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, и если да, инициализирует его: в Python 2.2 он устанавливается в &PyType_Type; в Python 2.2.1 и позднее он инициализируется полем ob_type базового класса. PyType_Ready() не изменяет это поле, если оно не равно нулю.

В Python 2.2 это поле не наследуется подтипами. В 2.2.1, а также в 2.3 и более поздних версиях, оно наследуется подтипами.

Py_ssize_t PyVarObject.ob_size

Для статически выделенных объектов-типов это поле должно быть инициализировано нулём. Для динамически выделенных объектов-типов это поле имеет особый внутренний смысл.

Это поле не наследуется подтипами.

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 экземпляра. Есть исключения: например, длинные целые (long ints) используют отрицательное ob_size для обозначения отрицательного числа, и N в этом случае равно abs(ob_size). Кроме того, наличие поля ob_size в структуре экземпляра не означает, что структура экземпляра имеет переменную длину (например, структура для типа списка имеет экземпляры фиксированной длины, но эти экземпляры содержат значимое поле ob_size).

Базовый размер включает поля экземпляра, объявленные макросом PyObject_HEAD или PyObject_VAR_HEAD (в зависимости от того, какой из них используется для объявления структуры экземпляра), и он, в свою очередь, включает поля _ob_prev и _ob_next, если они присутствуют. Это означает, что единственный правильный способ получить инициализатор для tp_basicsize – это использовать оператор sizeof для структуры, используемой для объявления макета экземпляра. Базовый размер не включает размер заголовка GC (это нововведение в Python 2.2; в версиях 2.1 и 2.0 размер заголовка GC включался в tp_basicsize).

Эти поля наследуются подтипами независимо друг от друга. Если базовый тип имеет ненулевое 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

Необязательный указатель на функцию печати экземпляра.

Функция печати вызывается только тогда, когда экземпляр выводится в реальный файл; при выводе в псевдофайл (например, экземпляр StringIO) вызывается функция tp_repr или tp_str экземпляра для преобразования его в строку. Они также вызываются, когда поле tp_print типа равно NULL. Тип никогда не должен реализовывать tp_print таким образом, чтобы выдавать вывод, отличный от того, что дали бы tp_repr или tp_str.

Функция печати вызывается с той же сигнатурой, что и PyObject_Print(): int tp_print(PyObject *self, FILE *file, int flags). Аргумент self – это печатаемый экземпляр. Аргумент file – это файл stdio, в который он должен быть выведен. Аргумент flags состоит из битовых флагов. Единственный определённый в настоящее время бит флага – Py_PRINT_RAW. Когда бит флага Py_PRINT_RAW установлен, экземпляр должен выводиться так же, как его отформатировал бы tp_str; когда бит флага Py_PRINT_RAW сброшен, экземпляр должен выводиться так же, как его отформатировал бы tp_repr. Функция должна возвращать -1 и устанавливать условие исключения при возникновении ошибки во время сравнения.

Возможно, поле tp_print будет объявлено устаревшим. В любом случае рекомендуется не определять tp_print, а вместо этого полагаться на tp_repr и tp_str для печати.

Это поле наследуется подтипами.

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.

cmpfunc PyTypeObject.tp_compare

Необязательный указатель на функцию тройного сравнения.

Сигнатура такая же, как у PyObject_Compare(). Функция должна возвращать 1, если self больше other, 0, если self равно other, и -1, если self меньше other. Она должна возвращать -1 и устанавливать условие исключения при возникновении ошибки во время сравнения.

Это поле наследуется подтипами вместе с tp_richcompare и tp_hash: подтип наследует все три: tp_compare, tp_richcompare и tp_hash, когда tp_compare, tp_richcompare и tp_hash подтипа все равны NULL.

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(); она должна возвращать C long. Значение -1 не должно возвращаться как обычное возвращаемое значение; при возникновении ошибки во время вычисления хеш-значения функция должна установить исключение и вернуть -1.

Это поле можно явно установить в PyObject_HashNotImplemented(), чтобы заблокировать наследование хеш-метода от родительского типа. Это интерпретируется как эквивалент __hash__ = None на уровне Python, в результате чего isinstance(o, collections.Hashable) корректно возвращает False. Обратите внимание, что верно и обратное: установка __hash__ = None в классе на уровне Python приведет к тому, что слот tp_hash будет установлен в PyObject_HashNotImplemented().

Если это поле не установлено, возможны два варианта: если поля tp_compare и tp_richcompare оба равны NULL, возвращается значение хеша по умолчанию на основе адреса объекта; в противном случае возбуждается TypeError.

Это поле наследуется подтипами вместе с tp_richcompare и tp_compare: подтип наследует все три tp_compare, tp_richcompare и tp_hash, когда поля tp_compare, 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 не наследуется, но содержащиеся в нём поля наследуются по отдельности.

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 в подтипе существуют (как указывает бит Py_TPFLAGS_HAVE_RICHCOMPARE) и имеют значения NULL.

В настоящее время определены следующие битовые маски; их можно объединять с помощью оператора | для получения значения поля tp_flags. Макрос PyType_HasFeature() принимает тип и значение флагов, tp и f, и проверяет, является ли tp->tp_flags & f ненулевым.

Py_TPFLAGS_HAVE_GETCHARBUFFER

Если этот бит установлен, структура PyBufferProcs, на которую ссылается tp_as_buffer, содержит поле bf_getcharbuffer.

Py_TPFLAGS_HAVE_SEQUENCE_IN

Если этот бит установлен, структура PySequenceMethods, на которую ссылается tp_as_sequence, содержит поле sq_contains.

Py_TPFLAGS_GC

Этот бит устарел. Бит, который он обозначал, больше не используется. Символ теперь определяется как ноль.

Py_TPFLAGS_HAVE_INPLACEOPS

Если этот бит установлен, структура PySequenceMethods, на которую ссылается tp_as_sequence, и структура PyNumberMethods, на которую ссылается tp_as_number, содержат поля для операций на месте (in-place). В частности, это означает, что структура PyNumberMethods имеет поля nb_inplace_add, nb_inplace_subtract, nb_inplace_multiply, nb_inplace_divide, nb_inplace_remainder, nb_inplace_power, nb_inplace_lshift, nb_inplace_rshift, nb_inplace_and, nb_inplace_xor и nb_inplace_or; а структура PySequenceMethods имеет поля sq_inplace_concat и sq_inplace_repeat.

Py_TPFLAGS_CHECKTYPES

Если этот бит установлен, бинарные и тернарные операции в структуре PyNumberMethods, на которую ссылается tp_as_number, принимают аргументы произвольных типов объектов и выполняют собственное преобразование типов при необходимости. Если этот бит сброшен, такие операции требуют, чтобы все аргументы имели текущий тип, и вызывающий должен сначала выполнить приведение (coercion). Это относится к nb_add, nb_subtract, nb_multiply, nb_divide, nb_remainder, nb_divmod, nb_power, nb_lshift, nb_rshift, nb_and, nb_xor и nb_or.

Py_TPFLAGS_HAVE_RICHCOMPARE

Если этот бит установлен, объект типа имеет поля tp_richcompare, tp_traverse и tp_clear.

Py_TPFLAGS_HAVE_WEAKREFS

Если этот бит установлен, поле tp_weaklistoffset определено. Экземпляры типа могут быть слабо ссылаемыми, если поле tp_weaklistoffset типа имеет значение больше нуля.

Py_TPFLAGS_HAVE_ITER

Если этот бит установлен, объект типа имеет поля tp_iter и tp_iternext.

Py_TPFLAGS_HAVE_CLASS

Если этот бит установлен, объект типа имеет несколько новых полей, определенных начиная с Python 2.2: tp_methods, tp_members, tp_getset, tp_base, tp_dict, tp_descr_get, tp_descr_set, tp_dictoffset, tp_init, tp_alloc, tp_new, tp_free, tp_is_gc, tp_bases, tp_mro, tp_cache, tp_subclasses и tp_weaklist.

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_HAVE_GC сброшен, а Py_TPFLAGS_HAVE_RICHCOMPARE установлен.

Py_TPFLAGS_DEFAULT

Это битовая маска всех битов, относящихся к наличию определенных полей в объекте типа и его структурах расширения. В настоящее время она включает следующие биты: Py_TPFLAGS_HAVE_GETCHARBUFFER, Py_TPFLAGS_HAVE_SEQUENCE_IN, Py_TPFLAGS_HAVE_INPLACEOPS, Py_TPFLAGS_HAVE_RICHCOMPARE, Py_TPFLAGS_HAVE_WEAKREFS, Py_TPFLAGS_HAVE_ITER и Py_TPFLAGS_HAVE_CLASS.

char* PyTypeObject.tp_doc

Необязательный указатель на C-строку, завершающуюся нулевым символом, содержащую строку документации для этого объекта типа. Это отображается как атрибут __doc__ у типа и его экземпляров.

Это поле не наследуется подтипами.

Следующие три поля существуют только если установлен бит флага Py_TPFLAGS_HAVE_RICHCOMPARE.

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 включила его.

Обратите внимание, что Py_VISIT() требует, чтобы параметры visit и arg для local_traverse() имели именно такие имена; не следует называть их как попало.

Это поле наследуется подтипами вместе с tp_clear и битом флага Py_TPFLAGS_HAVE_GC: бит флага, tp_traverse и tp_clear наследуются от базового типа, если в подтипе они все равны нулю и в подтипе установлен бит флага Py_TPFLAGS_HAVE_RICHCOMPARE.

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 наследуются от базового типа, если в подтипе они все равны нулю и в подтипе установлен бит флага Py_TPFLAGS_HAVE_RICHCOMPARE.

richcmpfunc PyTypeObject.tp_richcompare

Необязательный указатель на функцию расширенного сравнения (rich comparison), сигнатура которой – PyObject *tp_richcompare(PyObject *a, PyObject *b, int op).

Функция должна возвращать результат сравнения (обычно Py_True или Py_False). Если сравнение не определено, она должна вернуть Py_NotImplemented; если произошла другая ошибка, она должна вернуть NULL и установить условие исключения.

Примечание

Если требуется реализовать тип, для которого имеет смысл только ограниченный набор сравнений (например, == и !=, но не < и др.), следует напрямую возбуждать TypeError в функции расширенного сравнения.

Это поле наследуется подтипами вместе с tp_compare и tp_hash: подтип наследует все три tp_compare, tp_richcompare и tp_hash, когда поля tp_compare, tp_richcompare и tp_hash подтипа все равны NULL.

Следующие константы определены для использования в качестве третьего аргумента для tp_richcompare и для PyObject_RichCompare():

Константа

Сравнение

Py_LT

<

Py_LE

<=

Py_EQ

==

Py_NE

!=

Py_GT

>

Py_GE

>=

Следующее поле существует только если установлен бит флага Py_TPFLAGS_HAVE_WEAKREFS.

long 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 от своего базового типа.

Следующие два поля существуют только если установлен бит флага Py_TPFLAGS_HAVE_ITER.

getiterfunc PyTypeObject.tp_iter

Необязательный указатель на функцию, возвращающую итератор для объекта. Его наличие обычно означает, что экземпляры этого типа являются итерируемыми (хотя последовательности могут быть итерируемыми и без этой функции, а экземпляры классических классов всегда имеют эту функцию, даже если не определяют метод __iter__()).

Эта функция имеет ту же сигнатуру, что и PyObject_GetIter().

Это поле наследуется подтипами.

iternextfunc PyTypeObject.tp_iternext

Необязательный указатель на функцию, возвращающую следующий элемент итератора. Когда итератор исчерпан, она должна вернуть NULL; исключение StopIteration может быть установлено или не установлено. При возникновении другой ошибки она также должна вернуть NULL. Его наличие обычно означает, что экземпляры этого типа являются итераторами (хотя экземпляры классических классов всегда имеют эту функцию, даже если не определяют метод next()).

Типы-итераторы также должны определять функцию tp_iter, и эта функция должна возвращать сам экземпляр итератора (не новый экземпляр итератора).

Эта функция имеет ту же сигнатуру, что и PyIter_Next().

Это поле наследуется подтипами.

Следующие поля, вплоть до tp_weaklist включительно, существуют только если установлен бит флага Py_TPFLAGS_HAVE_CLASS.

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__()).

Это поле не наследуется подтипами (хотя определённые здесь атрибуты наследуются через другой механизм).

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);

Аргумент value устанавливается в NULL для удаления значения. Это поле наследуется подтипами.

long 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 подтипа. (ПРИМЕЧАНИЕ ПО ВЕРСИЯМ: здесь описано то, что реализовано в Python 2.2.1 и новее. В Python 2.2 всегда вызывался tp_init типа объекта, возвращаемого tp_new, если не NULL.)

Это поле наследуется подтипами.

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. Последнее исключение сделано в целях предосторожности, чтобы старые типы расширений не становились вызываемыми просто из-за связывания с Python 2.2.

destructor PyTypeObject.tp_free

Необязательный указатель на функцию освобождения экземпляра.

Сигнатура этой функции немного изменилась: в Python 2.2 и 2.2.1 её сигнатура – destructor:

void tp_free(PyObject *)

В Python 2.3 и новее её сигнатура – freefunc:

void tp_free(void *)

Единственный инициализатор, совместимый с обеими версиями, – это _PyObject_Del, чьё определение было соответствующим образом адаптировано в Python 2.3.

Это поле наследуется статическими подтипами, но не динамическими подтипами (подтипами, созданными выражением 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, определяет эту функцию, чтобы различать статически и динамически выделенные типы.)

Это поле наследуется подтипами. (ПРИМЕЧАНИЕ ПО ВЕРСИЯМ: в Python 2.2 оно не наследовалось. Оно наследуется в 2.2.1 и более новых версиях.)

PyObject* PyTypeObject.tp_bases

Кортеж базовых типов.

Это устанавливается для типов, созданных с помощью оператора class. Для статически определённых типов оно должно быть равно NULL.

Это поле не наследуется.

PyObject* PyTypeObject.tp_mro

Кортеж, содержащий расширенный набор базовых типов, начиная с самого типа и заканчивая object, в порядке разрешения методов (MRO).

Это поле не наследуется; оно вычисляется заново с помощью PyType_Ready().

PyObject* PyTypeObject.tp_cache

Не используется. Не наследуется. Только для внутреннего использования.

PyObject* PyTypeObject.tp_subclasses

Список слабых ссылок на подклассы. Не наследуется. Только для внутреннего использования.

PyObject* PyTypeObject.tp_weaklist

Голова списка слабых ссылок для слабых ссылок на этот объект типа. Не наследуется. Только для внутреннего использования.

Остальные поля определены только если определён макрос проверки возможностей COUNT_ALLOCS и предназначены только для внутреннего использования. Они dокументированы здесь для полноты. Ни одно из этих полей не наследуется подтипами. См. переменную окружения PYTHONSHOWALLOCCOUNT.

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_divide;
     binaryfunc nb_remainder;
     binaryfunc nb_divmod;
     ternaryfunc nb_power;
     unaryfunc nb_negative;
     unaryfunc nb_positive;
     unaryfunc nb_absolute;
     inquiry nb_nonzero;       /* Используется PyObject_IsTrue */
     unaryfunc nb_invert;
     binaryfunc nb_lshift;
     binaryfunc nb_rshift;
     binaryfunc nb_and;
     binaryfunc nb_xor;
     binaryfunc nb_or;
     coercion nb_coerce;       /* Используется функцией coerce() */
     unaryfunc nb_int;
     unaryfunc nb_long;
     unaryfunc nb_float;
     unaryfunc nb_oct;
     unaryfunc nb_hex;

     /* Добавлено в версии 2.0 */
     binaryfunc nb_inplace_add;
     binaryfunc nb_inplace_subtract;
     binaryfunc nb_inplace_multiply;
     binaryfunc nb_inplace_divide;
     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;

     /* Добавлено в версии 2.2 */
     binaryfunc nb_floor_divide;
     binaryfunc nb_true_divide;
     binaryfunc nb_inplace_floor_divide;
     binaryfunc nb_inplace_true_divide;

     /* Добавлено в версии 2.5 */
     unaryfunc nb_index;
} PyNumberMethods;

Бинарные и тернарные функции могут получать аргументы разных видов в зависимости от бита флага Py_TPFLAGS_CHECKTYPES:

  • Если Py_TPFLAGS_CHECKTYPES не установлен, гарантируется, что аргументы функции принадлежат типу объекта; вызывающая сторона отвечает за вызов метода приведения, заданного членом nb_coerce, для преобразования аргументов:

    coercion PyNumberMethods.nb_coerce

    Эта функция используется в PyNumber_CoerceEx() и имеет ту же сигнатуру. Первый аргумент всегда является указателем на объект определённого типа. Если возможно преобразование к общему «большему» типу, функция заменяет указатели на новые ссылки на преобразованные объекты и возвращает 0. Если преобразование невозможно, функция возвращает 1. Если установлено условие ошибки, она вернёт -1.

  • Если установлен флаг Py_TPFLAGS_CHECKTYPES, бинарные и тернарные функции должны проверять тип всех своих операндов и выполнять необходимые преобразования (по крайней мере один из операндов является экземпляром определённого типа). Это рекомендуемый способ; в Python 3 приведение полностью исчезнет.

Если операция не определена для данных операндов, бинарные и тернарные функции должны вернуть Py_NotImplemented; если произошла другая ошибка, они должны вернуть NULL и установить исключение.

Структуры объектов отображенияMapping Object Structures

PyMappingMethods

Эта структура хранит указатели на функции, которые объект использует для реализации протокола отображения. Она содержит три члена:

lenfunc PyMappingMethods.mp_length

Эта функция используется PyMapping_Length() и PyObject_Size() и имеет ту же сигнатуру. Этот слот может быть установлен в NULL, если у объекта нет определённой длины.

binaryfunc PyMappingMethods.mp_subscript

Эта функция используется PyObject_GetItem() и имеет ту же сигнатуру. Этот слот должен быть заполнен, чтобы функция PyMapping_Check() возвращала 1; в противном случае он может быть NULL.

objobjargproc PyMappingMethods.mp_ass_subscript

Эта функция используется PyObject_SetItem() и PyObject_DelItem(). Она имеет ту же сигнатуру, что и PyObject_SetItem(), но v также может быть установлено в NULL для удаления элемента. Если этот слот равен NULL, объект не поддерживает присваивание и удаление элементов.

Структуры объектов последовательностейSequence Object Structures

PySequenceMethods

Эта структура содержит указатели на функции, которые объект использует для реализации протокола последовательности.

lenfunc PySequenceMethods.sq_length

Эта функция используется PySequence_Size() и PyObject_Size(), и имеет ту же сигнатуру.

binaryfunc PySequenceMethods.sq_concat

Эта функция используется PySequence_Concat() и имеет ту же сигнатуру. Она также используется оператором + после попытки численного сложения через слот nb_add.

ssizeargfunc PySequenceMethods.sq_repeat

Эта функция используется PySequence_Repeat() и имеет ту же сигнатуру. Она также используется оператором * после попытки числового умножения через nb_multiply слот.

ssizeargfunc PySequenceMethods.sq_item

Эта функция используется PySequence_GetItem() и имеет ту же сигнатуру. Этот слот должен быть заполнен, чтобы функция PySequence_Check() возвращала 1; в противном случае он может быть NULL.

Отрицательные индексы обрабатываются следующим образом: если слот sq_length заполнен, он вызывается, и длина последовательности используется для вычисления положительного индекса, который передаётся в sq_item. Если sq_length равно NULL, индекс передаётся функции как есть.

ssizeobjargproc PySequenceMethods.sq_ass_item

Эта функция используется PySequence_SetItem() и имеет ту же сигнатуру. Этот слот может оставаться NULL, если объект не поддерживает присваивание и удаление элементов.

objobjproc PySequenceMethods.sq_contains

Эта функция может использоваться PySequence_Contains() и имеет ту же сигнатуру. Этот слот может оставаться NULL; в этом случае PySequence_Contains() просто проходит по последовательности, пока не найдёт совпадение.

binaryfunc PySequenceMethods.sq_inplace_concat

Эта функция используется PySequence_InPlaceConcat() и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его.

ssizeargfunc PySequenceMethods.sq_inplace_repeat

Эта функция используется PySequence_InPlaceRepeat() и имеет ту же сигнатуру. Она должна изменить свой первый операнд и вернуть его.

Структуры объектов буфераBuffer Object Structures

Буферный интерфейс предоставляет модель, в которой объект может раскрывать свои внутренние данные в виде набора блоков данных, где каждый блок задаётся парой указатель/длина. Эти блоки называются сегментами и предполагаются не смежными в памяти.

Если объект не предоставляет буферный интерфейс, его член tp_as_buffer в структуре PyTypeObject должен быть NULL. В противном случае tp_as_buffer будет указывать на структуру PyBufferProcs.

Примечание

Очень важно, чтобы ваша структура PyTypeObject использовала Py_TPFLAGS_DEFAULT в качестве значения члена tp_flags, а не 0. Это сообщает среде выполнения Python, что ваша структура PyBufferProcs содержит слот bf_getcharbuffer. В старых версиях Python этого члена не было, поэтому новая версия интерпретатора Python, использующая старое расширение, должна уметь проверять его наличие перед использованием.

PyBufferProcs

Структура, используемая для хранения указателей на функции, определяющие реализацию протокола буфера.

Первый слот – bf_getreadbuffer, типа readbufferproc. Если этот слот равен NULL, то объект не поддерживает чтение внутренних данных. Это бессмысленно, поэтому разработчики должны заполнять этот слот, но вызывающие стороны должны проверять, что слот содержит значение, отличное от NULL.

Следующий слот – bf_getwritebuffer, с типом writebufferproc. Этот слот может быть NULL, если объект не разрешает запись в возвращаемые буферы.

Третий слот – bf_getsegcount, с типом segcountproc. Этот слот не должен быть NULL и используется для сообщения вызывающей стороне о количестве сегментов, которые содержит объект. Простые объекты, такие как PyString_Type и PyBuffer_Type, содержат один сегмент.

Последний слот – bf_getcharbuffer, типа charbufferproc. Этот слот будет присутствовать, только если флаг Py_TPFLAGS_HAVE_GETCHARBUFFER присутствует в поле tp_flags структуры PyTypeObject объекта. Перед использованием этого слота вызывающая сторона должна проверить его наличие с помощью функции PyType_HasFeature(). Если флаг присутствует, bf_getcharbuffer может быть NULL, что означает, что содержимое объекта не может использоваться как 8-битные символы. Слотовая функция также может вызвать ошибку, если содержимое объекта не удаётся интерпретировать как 8-битные символы. Например, если объект является массивом, настроенным на хранение чисел с плавающей точкой, может быть возбуждено исключение, если вызывающая сторона попытается использовать bf_getcharbuffer для получения последовательности 8-битных символов. Это понятие экспорта внутренних буферов как «текста» используется для различения объектов, имеющих двоичную природу, и объектов с символьным содержимым.

Примечание

Текущая политика, по-видимому, утверждает, что эти символы могут быть многобайтовыми. Это означает, что размер буфера N не означает, что присутствует N символов.

Py_TPFLAGS_HAVE_GETCHARBUFFER

Бит флага, установленный в структуре типа, чтобы указать, что слот bf_getcharbuffer известен. Его установка не означает, что объект поддерживает буферный интерфейс или что слот bf_getcharbuffer не равен NULL.

Py_ssize_t (*readbufferproc)(PyObject *self, Py_ssize_t segment, void **ptrptr)

Возвращает указатель на читаемый сегмент буфера в *ptrptr. Эта функция может вызывать исключение; в этом случае она должна вернуть -1. Указанный сегмент должен быть нулевым или положительным и строго меньше количества сегментов, возвращаемых функцией слота bf_getsegcount. В случае успеха возвращается длина сегмента, а *ptrptr устанавливается в указатель на эту память.

Py_ssize_t (*writebufferproc)(PyObject *self, Py_ssize_t segment, void **ptrptr)

Возвращает указатель на буфер памяти для записи в *ptrptr, а длину этого сегмента – как возвращаемое значение функции. Буфер памяти должен соответствовать сегменту буфера сегмент. Должен вернуть -1 и установить исключение при ошибке. TypeError должно быть вызвано, если объект поддерживает только буферы только для чтения, а SystemError – когда сегмент указывает на несуществующий сегмент.

Py_ssize_t (*segcountproc)(PyObject *self, Py_ssize_t *lenp)

Возвращает количество сегментов памяти, составляющих буфер. Если lenp не равно NULL, реализация должна вернуть сумму размеров (в байтах) всех сегментов в *lenp. Эта функция не может завершиться ошибкой.

Py_ssize_t (*charbufferproc)(PyObject *self, Py_ssize_t segment, char **ptrptr)

Возвращает размер сегмента сегмент, на который указывает ptrptr. *ptrptr устанавливается на буфер памяти. В случае ошибки возвращает -1.