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

Буферные объектыBuffer Objects

Объекты Python, реализованные на C, могут экспортировать «буферный интерфейс». Эти функции могут использоваться объектом для предоставления своих данных в сыром, ориентированном на байты формате. Клиенты объекта могут использовать буферный интерфейс для прямого доступа к данным объекта без необходимости их предварительного копирования.

Два примера объектов, поддерживающих буферный интерфейс: bytes и arrays. Объект bytes предоставляет содержимое символов в байт-ориентированной форме буферного интерфейса. Массив также может предоставлять своё содержимое, однако следует отметить, что элементы массива могут быть многобайтовыми.

Примером использования буферного интерфейса является метод write() файлового объекта. Любой объект, который может экспортировать последовательность байтов через буферный интерфейс, может быть записан в файл. Существует ряд кодов формата для PyArg_ParseTuple, которые работают с буферным интерфейсом объекта, возвращая данные из целевого объекта.

Дополнительная информация о буферном интерфейсе приведена в разделе Структуры буферных объектов, в описании PyBufferProcs.

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

Py_buffer
void *buf
Указатель на начало памяти объекта.
Py_ssize_t len
Общая длина памяти в байтах.
int readonly
Индикатор того, является ли буфер доступным только для чтения.
const char *format
Строка, завершающаяся нулём NULL, в синтаксисе стиля модуля struct, задающая содержимое элементов, доступных через буфер. Если это NULL, то предполагается "B" (беззнаковые байты).
int ndim
Количество измерений, которые память представляет как многомерный массив. Если оно равно 0, strides и suboffsets должны быть NULL.
Py_ssize_t *shape
Массив Py_ssize_t длиной ndim, задающий форму памяти как многомерного массива. Обратите внимание, что ((*shape)[0] * ... * (*shape)[ndims-1])*itemsize должно быть равно len.
Py_ssize_t *strides
Массив Py_ssize_t длиной ndim, задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.
Py_ssize_t *suboffsets

Массив Py_ssize_t длиной ndim. Если эти числа suboffset больше или равны 0, то значение, хранящееся по указанному измерению, является указателем, а значение suboffset определяет, сколько байтов добавить к указателю после разыменования. Отрицательное значение suboffset означает, что разыменование не должно выполняться (шаг в непрерывном блоке памяти).

Вот функция, которая возвращает указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых strides, так и suboffsets:

void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,
    Py_ssize_t *suboffsets, Py_ssize_t *indices) {
    char *pointer = (char*)buf;
    int i;
    for (i = 0; i < ndim; i++) {
        pointer += strides[i] * indices[i];
        if (suboffsets[i] >=0 ) {
            pointer = *((char**)pointer) + suboffsets[i];
        }
    }
    return (void*)pointer;
 }
Py_ssize_t itemsize
Это хранилище для размера элемента (в байтах) каждого элемента разделяемой памяти. Технически оно необязательно, так как его можно получить с помощью PyBuffer_SizeFromFormat, однако экспортёр может знать эту информацию без разбора строки формата, и необходимо знать размер элемента для правильной интерпретации шагов (striding). Поэтому сохранение его более удобно и быстрее.
void *internal
Это поле предназначено для внутреннего использования экспортирующим объектом. Например, оно может быть переинтерпретировано как целое число экспортером и использоваться для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель никогда не должен изменять это значение.

Объекты MemoryViewMemoryView objects

Объект memoryview – это расширенный буферный объект, который может заменить буферный объект (но не обязан, так как тот может оставаться простым одномерным объектом memoryview объект). Он, в отличие от Py_buffer, является объектом Python (предоставляется как memoryview в builtins), поэтому его можно использовать в коде Python.

PyObject* PyMemoryView_FromObject(PyObject *obj)
Возвращает объект memoryview из объекта, который определяет буферный интерфейс.