Общие структуры объектов

Существует большое количество структур, которые используются при определении типов объектов для Python. В этом разделе описаны данные структуры и их использование.

В конечном итоге все объекты Python совместно используют небольшое количество полей в начале представления объекта в памяти. Они представлены типами PyObject и PyVarObject, которые, в свою очередь, определяются расширениями некоторых макросов, которые также используются прямо или косвенно в определении всех других объектов Python.

PyObject

Все типы объектов являются расширениями этого типа. Данный тип содержит информацию, необходимую Python для обработки указателя на объект как объекта. В обычной «релизной» сборке он содержит только счётчик ссылок на объект и указатель на объект соответствующего типа. Фактически ничего не объявляется как PyObject, но каждый указатель на объект Python может быть приведён к PyObject*. Доступ к членам должен осуществляться с помощью макросов Py_REFCNT и Py_TYPE.

PyVarObject

Это расширение PyObject, которое добавляет поле ob_size. Используется только для объектов, у которых есть некоторое представление о length. Данный тип не часто появляется в API Python/C. Доступ к членам должен осуществляться с помощью макросов Py_REFCNT, Py_TYPE и Py_SIZE.

PyObject_HEAD

Данный макрос используется при объявлении новых типов, которые представляют объекты без переменной длины. Макрос PyObject_HEAD расширяется до:

PyObject ob_base;

См. документацию PyObject выше.

PyObject_VAR_HEAD

Данный макрос используется при объявлении новых типов, которые представляют объекты, длина которых варьируется от экземпляра к экземпляру. Макрос PyObject_VAR_HEAD расширяется до:

PyVarObject ob_base;

См. документацию PyVarObject выше.

Py_TYPE(o)

Данный макрос используется для доступа к члену ob_type объекта Python. Он расширяется до:

(((PyObject*)(o))->ob_type)
Py_REFCNT(o)

Данный макрос используется для доступа к члену ob_refcnt объекта Python. Он расширяется до:

(((PyObject*)(o))->ob_refcnt)
Py_SIZE(o)

Данный макрос используется для доступа к члену ob_size объекта Python. Он расширяется до:

(((PyVarObject*)(o))->ob_size)
PyObject_HEAD_INIT(type)

Макрос, расширяемый до значений инициализации для нового типа PyObject. Данный макрос расширяется до:

_PyObject_EXTRA_INIT
1, type,
PyVarObject_HEAD_INIT(type, size)

Макрос, расширяемый до значений инициализации для нового типа PyVarObject, включая поле ob_size. Данный макрос расширяется до:

_PyObject_EXTRA_INIT
1, type, size,
PyCFunction

Тип функций, используемых для реализации большинства вызываемых Python в C. Функции этого типа принимают два параметра PyObject* и возвращают одно такое значение. Если возвращаемое значение — NULL, должно быть установлено исключение. Если не NULL, возвращаемое значение интерпретируется как возвращаемое значение функции, представленной в Python. Функция должна возвращает новую ссылку.

PyCFunctionWithKeywords

Тип функций, используемых для реализации вызовов Python на C с сигнатураю METH_VARARGS | METH_KEYWORDS.

_PyCFunctionFast

Тип функций, используемых для реализации вызовов Python на C с сигнатураю METH_FASTCALL.

_PyCFunctionFastWithKeywords

Тип функций, используемых для реализации вызовов Python на C с сигнатураю METH_FASTCALL | METH_KEYWORDS.

PyMethodDef

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

Поле C тип Смысл
ml_name const char * имя метода
ml_meth PyCFunction указатель на C реализацию
ml_flags int биты флага, указывающие, как должен быть построен вызов
ml_doc const char * указывает на содержимое докстринга

ml_meth — это указатель на функцию C. Функции могут быть разных типов, но всегда возвращают PyObject*. Если функция не из PyCFunction, компилятор потребует приведение в таблице методов. Несмотря на то, что PyCFunction определяет первый параметр как PyObject*, обычно реализация метода использует тип C объекта self.

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

Существует четыре основных соглашения о вызове позиционных аргументов, и два из них могут быть объединены с METH_KEYWORDS для поддержки также ключевых аргументов. Итак, всего существует 6 соглашений о вызовах:

METH_VARARGS

Это типичное соглашение о вызовах, в котором у методов есть тип PyCFunction. Функция ожидает два значения PyObject*. Первый — это объект self для методов; для функций модуля это объект модуля. Второй параметр (часто называемый args) — это объект кортежа, представляющий все аргументы. Данный параметр обычно обрабатывается с использованием PyArg_ParseTuple() или PyArg_UnpackTuple().

METH_VARARGS | METH_KEYWORDS

Методы с этими флагами должны быть типа PyCFunctionWithKeywords. Функция ожидает трёх параметров: self, args, kwargs, где kwargs — словарь всех ключевых аргументов или, возможно, NULL, если ключевых аргументов нет. Параметры обычно обрабатываются с использованием PyArg_ParseTupleAndKeywords().

METH_FASTCALL

Соглашение о быстром вызове, поддерживающее только позиционные аргументы. У методов тип _PyCFunctionFast. Первый параметр — self, второй параметр — это C-массив значений PyObject*, указывающих аргументы, а третий параметр — количество аргументов (длина массива).

Это не часть ограничения API.

Добавлено в версии 3.7.

METH_FASTCALL | METH_KEYWORDS

Расширение METH_FASTCALL, поддерживающее также ключевые аргументы с методами типа _PyCFunctionFastWithKeywords. Ключевые аргументы передаются так же, как в протоколе vectorcall: есть дополнительный четвёртый параметр PyObject*, который представляет собой кортеж, представляющий имена ключевых аргументов или, возможно, NULL, если нет ключевых слов. Значения ключевых аргументов хранятся в массиве args после позиционных аргументов.

Это не часть ограничения API.

Добавлено в версии 3.7.

METH_NOARGS

Методам без параметров не нужно проверять, указаны ли аргументы, если они указаны с флагом METH_NOARGS. Они должны быть типа PyCFunction. Первый параметр обычно называется self и будет содержать ссылку на модуль или экземпляр объекта. Во всех случаях второй параметр будет NULL.

METH_O

Методы с одним аргументом объекта могут быть перечислены с флагом METH_O вместо вызова PyArg_ParseTuple() с аргументом "O". У них тип PyCFunction с параметром self и параметром PyObject*, представляющим единственный аргумент.

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

METH_CLASS

В метод будет передан объект типа в качестве первого параметра, а не экземпляр типа. Это используется для создания методов класса, аналогично тому, что создаётся при использовании встроенной функции classmethod().

METH_STATIC

В метод будет передан NULL как первый параметр, а не как экземпляр типа. Это используется для создания статических методов, аналогично тому, что создается при использовании встроенной функции staticmethod().

Ещё одна константа контролирует, загружается ли метод вместо другого определения с тем же именем метода.

METH_COEXIST

Метод будет загружен вместо существующих определений. Без METH_COEXIST по умолчанию повторяющиеся определения пропускаются. Поскольку оболочки слотов загружаются перед таблицей методов, наличие слота sq_contains, например, приведёт к созданию обернутого метода с именем __contains__() и предотвратит загрузку соответствующей функции PyCFunction с тем же именем. С определенным флагом PyCFunction будет загружен вместо объекта-оболочки и будет сосуществовать со слотом. Это полезно, потому что вызовы PyCFunctions оптимизированы больше, чем вызовы объектов оболочки.

PyMemberDef

Структура, которая определяет атрибут типа, который соответствует члену структуры C. Его поля следующие:

Поле C тип Смысл
name const char * имя члена
type int тип члена в C структуре
offset Py_ssize_t смещение в байтах, в котором член расположен в структуре типа объекта
flags int биты флага, указывающие, должно ли поле быть доступным только для чтения или для записи
doc const char * указывает на содержимое докстринга

type может быть одним из многих макросов T_, соответствующих различным типам C. Когда к члену обращаются в Python, он будет преобразован в эквивалентный Python тип.

Имя макро C тип
T_SHORT short
T_INT int
T_LONG long
T_FLOAT float
T_DOUBLE double
T_STRING const char *
T_OBJECT PyObject *
T_OBJECT_EX PyObject *
T_CHAR char
T_BYTE char
T_UBYTE unsigned char
T_UINT unsigned int
T_USHORT unsigned short
T_ULONG unsigned long
T_BOOL char
T_LONGLONG long long
T_ULONGLONG unsigned long long
T_PYSSIZET Py_ssize_t

T_OBJECT и T_OBJECT_EX отличаются тем, что T_OBJECT возвращает None, если член NULL, а T_OBJECT_EX вызывает AttributeError. Попытайтесь использовать T_OBJECT_EX вместо T_OBJECT, потому что T_OBJECT_EX обрабатывает использование оператора del для этого атрибута более правильно, чем T_OBJECT.

flags может быть 0 для доступа для записи и чтения или READONLY для доступа только для чтения. Использование T_STRING для type подразумевает READONLY. Данные T_STRING интерпретируются как UTF-8. Только члены T_OBJECT и T_OBJECT_EX могут быть удалены. (Они установлены на NULL).

PyGetSetDef

Структура для определения доступа к типу, подобному свойствам. См. также описание слота PyTypeObject.tp_getset.

Поле C тип Смысл
name const char * имя атрибута
get getter C функция для получения атрибута
set setter необязательная C функция для установки или удаления атрибута, если пропущенный атрибут только для чтения
doc const char * опциональный докстринг
closure void * необязательный указатель функции, предоставляющий дополнительные данные для геттера и сеттера

Функция get принимает один параметр PyObject* (экземпляр) и указатель функции (связанное closure):

typedef PyObject *(*getter)(PyObject *, void *);

Она должна возвращать новую ссылку в случае успеха или NULL с заданным исключением в случае ошибки.

Функции set принимают два параметра PyObject* (экземпляр и значение, которое нужно установить) и указатель функции (связанное closure):

typedef int (*setter)(PyObject *, PyObject *, void *);

Если атрибут необходимо удалить, второй параметр — NULL. Должен возвращать 0 в случае успеха или -1 с заданным исключением в случае неудачи.