Объекты типов¶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¶
These fields are only present when the macro Py_TRACE_REFS is defined. Their initialization to NULL is taken care of by the PyObject_HEAD_INIT macro. For statically allocated objects, these fields always remain NULL. For dynamically allocated objects, these two fields are used to link the object into a doubly-linked list of all live objects on the heap. This could be used for various debugging purposes; currently the only use is to print the objects that are still alive at the end of a run when the environment variable PYTHONDUMPREFS is set.
Эти поля не наследуются подтипами.
- 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.
Это поле не наследуется подтипами.
- 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 int используют отрицательное 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_GetAttrString().
Это поле наследуется подтипами вместе с tp_getattro: подтип наследует и tp_getattr, и tp_getattro от своего базового типа, когда tp_getattr и tp_getattro подтипа оба равны NULL.
- setattrfunc PyTypeObject.tp_setattr¶
Необязательный указатель на функцию установки строкового атрибута.
Это поле устарело. Если оно определено, оно должно указывать на функцию, которая ведет себя так же, как tp_setattro, но принимает строку C вместо строкового объекта Python для указания имени атрибута. Сигнатура такая же, как у PyObject_SetAttrString().
Это поле наследуется подтипами вместе с 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(). Обычно удобно устанавливать это поле в 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-строку, завершающуюся NUL, содержащую строку документации для этого объекта типа. Он доступен как атрибут __doc__ у типа и его экземпляров.
Это поле не наследуется подтипами.
Следующие три поля существуют только в том случае, если установлен бит флага Py_TPFLAGS_HAVE_RICHCOMPARE.
- traverseproc PyTypeObject.tp_traverse¶
Необязательный указатель на функцию обхода для сборщика мусора. Используется только если установлен бит флага Py_TPFLAGS_HAVE_GC. Дополнительную информацию о схеме сборки мусора в Python можно найти в разделе Supporting Cyclic Garbage Collection.
Указатель tp_traverse используется сборщиком мусора для обнаружения циклических ссылок. Типичная реализация функции tp_traverse просто вызывает Py_VISIT() для каждого из членов экземпляра, являющихся объектами Python. Например, это функция local_traverse() из модуля расширения поток:
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 и реализовать функцию tp_dealloc типа так, чтобы она вызывала tp_clear.
Дополнительную информацию о схеме сборки мусора Python можно найти в разделе Поддержка циклической сборки мусора.
Это поле наследуется подтипами вместе с tp_traverse и флагом Py_TPFLAGS_HAVE_GC: флаг, tp_traverse и tp_clear наследуются от базового типа, если все они равны нулю в подтипе и подтип имеет установленным флаг Py_TPFLAGS_HAVE_RICHCOMPARE.
- richcmpfunc PyTypeObject.tp_richcompare¶
Необязательный указатель на функцию сравнения с сигнатурой: 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, объявляющий вычисляемые атрибуты экземпляров этого типа.
Для каждой записи массива в словарь типа (см. tp_dict ниже) добавляется запись, содержащая дескриптор getset.
Это поле не наследуется подтипами (вычисляемые атрибуты наследуются через другой механизм).
Документация для PyGetSetDef (XXX должна быть в другом месте):
typedef PyObject *(*getter)(PyObject *, void *); typedef int (*setter)(PyObject *, PyObject *, void *); typedef struct PyGetSetDef { char *name; /* имя атрибута */ getter get; /* C-функция для получения атрибута */ setter set; /* C-функция для установки атрибута */ char *doc; /* необязательная строка документации */ void *closure; /* необязательные дополнительные данные для геттера и сеттера */ } PyGetSetDef;
- 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);
XXX объяснить.
Это поле наследуется подтипами.
- descrsetfunc PyTypeObject.tp_descr_set¶
Необязательный указатель на функцию «установки дескриптора».
Сигнатура функции:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
Это поле наследуется подтипами.
XXX объяснить.
- 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, установленным в аргумент 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окументированы здесь для полноты. Ни одно из этих полей не наследуется подтипами.
- 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.0 приведение типов исчезнет полностью.
Если операция не определена для данных операндов, бинарные и тернарные функции должны вернуть 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() и имеет ту же сигнатуру. Если этот слот равен NULL, объект не поддерживает присваивание по индексу.
Структуры объектов последовательностей¶Sequence Object Structures
- PySequenceMethods¶
- Эта структура содержит указатели на функции, которые объект использует для реализации протокола последовательности.
- lenfunc PySequenceMethods.sq_length¶
- Эта функция используется функциями PySequence_Size() и PyObject_Size(), и имеет ту же сигнатуру.
- binaryfunc PySequenceMethods.sq_concat¶
- Эта функция используется PySequence_Concat() и имеет ту же сигнатуру. Она также используется оператором + после попытки числового сложения через слот tp_as_number.nb_add.
- ssizeargfunc PySequenceMethods.sq_repeat¶
- Эта функция используется PySequence_Repeat() и имеет ту же сигнатуру. Она также используется оператором * после попытки числового умножения через слот tp_as_number.nb_mul.
- 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() и имеет ту же\nсигнатуру. Этот слот можно оставить равным NULL; в этом случае\nPySequence_Contains() просто обходит последовательность, пока не найдёт\nсовпадение.
- binaryfunc PySequenceMethods.sq_inplace_concat¶
- Эта функция используется PySequence_InPlaceConcat() и имеет ту же\nсигнатуру. Она должна изменить свой первый операнд и вернуть его.
- ssizeargfunc PySequenceMethods.sq_inplace_repeat¶
- Эта функция используется PySequence_InPlaceRepeat() и имеет ту же\nсигнатуру. Она должна изменить свой первый операнд и вернуть его.
Структуры объектов буфера¶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, типа getreadbufferproc. Если этот слот равен NULL, то объект не поддерживает чтение из внутренних данных. Это бессмысленно, поэтому разработчики должны его заполнить, но вызывающие код должны проверять, что слот содержит не-NULL значение.
Следующий слот – bf_getwritebuffer, имеющий тип getwritebufferproc. Этот слот может быть NULL, если объект не разрешает запись в свои возвращаемые буферы.
Третий слот – bf_getsegcount, типа getsegcountproc. Этот слот не должен быть NULL и используется для информирования вызывающего о том, сколько сегментов содержит объект. Простые объекты, такие как PyString_Type и PyBuffer_Type, содержат один сегмент.
Последний слот – bf_getcharbuffer, типа getcharbufferproc. Этот слот будет присутствовать только в том случае, если флаг 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. Указанный segment должен быть неотрицательным и строго меньше количества сегментов, возвращаемых функцией слота bf_getsegcount. При успехе возвращает длину сегмента и устанавливает *ptrptr в указатель на эту память.
- Py_ssize_t (*writebufferproc)(PyObject *self, Py_ssize_t segment, void **ptrptr)¶
- Возвращает указатель на доступный для записи буфер памяти в *ptrptr и длину этого сегмента как возвращаемое значение функции. Буфер памяти должен соответствовать сегменту буфера segment. Должен вернуть -1 и установить исключение при ошибке. TypeError должно быть возбуждено, если объект поддерживает только буферы только для чтения, и SystemError должно быть возбуждено, когда segment указывает сегмент, который не существует.