Spec-Zone.ru › NumPy 1.17

Интерфейс массива

Примечание

Эта страница описывает API, специфичный для numpy, для доступа к содержимому массива numpy из других расширений C. PEP 3118 – The Revised Buffer Protocol вводит аналогичный стандартизованный API для модулей расширения Python 2.6 и 3.0. Поддержка буферных массивов в PEP 3118 используется в Cython; см. учебник по Cython и numpy. Cython предоставляет способ написания кода, который поддерживает протокол буфера с версиями Python, более старыми, чем 2.6, так как он имеет обратную совместимость с реализацией, использующей интерфейс массива, описанный здесь.

версия: 3

Интерфейс массива (иногда называемый протоколом массива) был создан в 2005 году как средство для объектов Python, подобных массивам, для разумного повторного использования буферов данных друг друга, когда это возможно. Однородный интерфейс N-мерного массива является механизмом по умолчанию для объектов, чтобы совместно использовать память и информацию о N-мерном массиве. Интерфейс состоит из стороны Python и стороны C, используя два атрибута. Объекты, которые хотят считаться N-мерным массивом в прикладном коде, должны поддерживать хотя бы один из этих атрибутов. Объекты, желающие поддерживать N-мерный массив в прикладном коде, должны искать хотя бы один из этих атрибутов и использовать предоставленную информацию должным образом.

Этот интерфейс описывает однородные массивы в том смысле, что каждый элемент массива имеет один и тот же «тип». Этот тип может быть очень простым или достаточно произвольным и сложным структурой, подобной C.

Существует два способа использования интерфейса: с Python-стороны и с C-стороны. Оба являются отдельными атрибутами.

Python-сторона

Этот подход к интерфейсу состоит из объекта, имеющего атрибут __array_interface__.

__array_interface__

Словарь элементов (3 обязательных и 5 необязательных). Необязательные ключи в словаре имеют подразумеваемые значения по умолчанию, если они не предоставлены.

Ключи:

shape (обязательный)

Кортеж, элементы которого представляют размер массива в каждой размерности. Каждый элемент — целое число (Python int или long). Обратите внимание, что эти целые числа могут быть больше, чем может содержать платформа «int» или «long» (Python int — это C long). Код, использующий этот атрибут, должен должным образом обрабатывать это; либо путем повышения ошибки, когда переполнение возможно, или путем использования Py_LONG_LONG в качестве типа C для размеров.

typestr (обязательный)

Строка, предоставляющая базовый тип однородного массива. Основной формат строки состоит из 3 частей: символ, описывающий порядок байтов данных (<: little-endian, >: big-endian, |: нерелевантно), символ, определяющий базовый тип массива, и целое число, указывающее количество байт, используемых типом.

Основные символы типов:

t Поле бита (следующее целое число указывает количество битов в поле бита).
b Булево (целочисленный тип, где все значения — только True или False)
i Целое число
u Беззнаковое целое число
f Число с плавающей точкой
c Комплексное число с плавающей точкой
m Timedelta
M Datetime
O Объект (т. е. память содержит указатель на PyObject)
S Строка (последовательность фиксированной длины символов)
U Unicode (последовательность фиксированной длины Py_UNICODE)
V Другое (void * — каждый элемент — фиксированный кусок памяти)

descr (необязательный)

Список кортежей, предоставляющий более подробное описание расположения памяти для каждого элемента в однородном массиве. Каждый кортеж в списке имеет два или три элемента. Обычно этот атрибут используется, когда typestr является V[0-9]+, но это не обязательно. Единственное требование заключается в том, чтобы количество байтов, представленных в ключе typestr, совпадало с общим количеством байтов, представленных здесь. Идея состоит в том, чтобы поддерживать описания структур, похожих на C, которые составляют элементы массива. Элементами каждого кортежа в списке являются

  1. Строка, предоставляющая имя, связанное с этой частью типа данных. Это также может быть кортеж из ('full name', 'basic_name'), где базовым именем будет действительное имя Python-переменной, представляющее полное имя поля.
  2. Описание базового типа, как в typestr, или другой список (для вложенных структурированных типов)
  3. Необязательный кортеж shape, указывающий, сколько раз эта часть структуры должна повторяться. Если это не указано, повторений не предполагается. Очень сложные структуры могут быть описаны с помощью этого универсального интерфейса. Обратите внимание, что каждый элемент массива по-прежнему имеет один и тот же тип данных.

Значение по умолчанию: [('', typestr)]

data (необязательный)

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

Этот атрибут также может быть объектом, экспонирующим buffer interface, который будет использоваться для совместного использования данных. Если этот ключ отсутствует (или возвращает None), то совместное использование памяти будет выполняться через интерфейс буфера самого объекта. В этом случае ключ offset может использоваться для указания начала буфера. Ссылка на объект, экспонирующий интерфейс массива, должна храниться новым объектом, если область памяти должна быть защищена.

Значение по умолчанию: None

strides (необязательный)

Либо None для указания массива, выровненного по стилю C, или кортеж смещений, который содержит количество байтов, необходимых для перехода к следующему элементу массива в соответствующей размерности. Каждый элемент должен быть целым числом (Python int или long). Как и в случае с shape, значения могут быть больше, чем могут быть представлены C «int» или «long»; вызывающий код должен обрабатывать это должным образом, либо путем повышения ошибки, либо путем использования Py_LONG_LONG в C. Значение по умолчанию — None , что подразумевает буфер памяти, выровненный по стилю C. В этой модели последняя размерность массива изменяется быстрее всего. Например, кортеж смещений по умолчанию для объекта, элементы массива которого имеют длину 8 байтов, а shape — (10,20,30), будет (4800, 240, 8)

Значение по умолчанию: None (выровнен по стилю C)

mask (необязательный)

None или объект, экспонирующий интерфейс массива. Все элементы массива маски должны интерпретироваться только как истинные или ложные, указывающие, какие элементы этого массива допустимы. Размер этого объекта должен быть “broadcastable” размером исходного массива.

Значение по умолчанию: None (все значения массива допустимы)

offset (необязательный)

Смещение целого числа в области данных массива. Это может использоваться только тогда, когда данные None или возвращают объект buffer.

Значение по умолчанию: 0.

version (обязательный)

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

Доступ к структуре C

Этот подход к интерфейсу массива позволяет быстрее обращаться к массиву, используя только один поиск атрибута и хорошо определенную структуру C.

__array_struct__

Тип :c:type: PyCObject , члены voidptr содержат указатель на заполненную структуру PyArrayInterface. Память для структуры создается динамически, и PyCObject также создается со соответствующим деструктором, так что получатель этого атрибута просто должен применить Py_DECREF к возвращаемому этим атрибутом объекту, когда он закончит работу. Кроме того, либо данные должны быть скопированы, либо должна храниться ссылка на объект, экспонирующий этот атрибут, чтобы гарантировать, что данные не будут освобождены. Объекты, экспонирующие интерфейс __array_struct__ , также не должны перевыделять свою память, если на них ссылаются другие объекты.

Структура PyArrayInterface определяется в numpy/ndarrayobject.h как:

typedef struct {
  int two;              /* contains the integer 2 -- simple sanity check */
  int nd;               /* number of dimensions */
  char typekind;        /* kind in array --- character code of typestr */
  int itemsize;         /* size of each element */
  int flags;            /* flags indicating how the data should be interpreted */
                        /*   must set ARR_HAS_DESCR bit to validate descr */
  Py_intptr_t *shape;   /* A length-nd array of shape information */
  Py_intptr_t *strides; /* A length-nd array of stride information */
  void *data;           /* A pointer to the first element of the array */
  PyObject *descr;      /* NULL or data-description (same as descr key
                                of __array_interface__) -- must set ARR_HAS_DESCR
                                flag or this will be ignored. */
} PyArrayInterface;

Поле флагов может состоять из 5 битов, показывающих, как должны интерпретироваться данные, и одного бита, показывающего, как должен интерпретироваться интерфейс. Битами данных являются CONTIGUOUS (0x1), FORTRAN (0x2), ALIGNED (0x100), NOTSWAPPED (0x200) и WRITEABLE (0x400). Конечный флаг ARR_HAS_DESCR (0x800) указывает, присутствует ли поле arrdescr.

Новые с 16 июня 2006 года:

В прошлом большинство реализаций использовали член “desc” объекта PyCObject (не путать с членом “descr” структуры PyArrayInterface выше — это разные вещи) для хранения указателя на объект, экспонирующий интерфейс. Теперь это явная часть интерфейса. Убедитесь, что у вас есть ссылка на объект, когда объект PyCObject создаётся с помощью PyCObject_FromVoidPtrAndDesc.

Примеры описания типа

Для ясности полезно привести несколько примеров описания типа и соответствующих записей ‘descr’ для __array_interface__. Спасибо Скотту Гильберту за эти примеры:

В каждом случае ключ ‘descr’ является необязательным, но, конечно, предоставляет больше информации, которая может быть важной для различных приложений:

* Float data
    typestr == '>f4'
    descr == [('','>f4')]

* Complex double
    typestr == '>c8'
    descr == [('real','>f4'), ('imag','>f4')]

* RGB Pixel data
    typestr == '|V3'
    descr == [('r','|u1'), ('g','|u1'), ('b','|u1')]

* Mixed endian (weird but could happen).
    typestr == '|V8' (or '>u8')
    descr == [('big','>i4'), ('little','<i4')]

* Nested structure
    struct {
        int ival;
        struct {
            unsigned short sval;
            unsigned char bval;
            unsigned char cval;
        } sub;
    }
    typestr == '|V8' (or '<u8' if you want)
    descr == [('ival','<i4'), ('sub', [('sval','<u2'), ('bval','|u1'), ('cval','|u1') ]) ]

* Nested array
    struct {
        int ival;
        double data[16*4];
    }
    typestr == '|V516'
    descr == [('ival','>i4'), ('data','>f8',(16,4))]

* Padded structure
    struct {
        int ival;
        double dval;
    }
    typestr == '|V16'
    descr == [('ival','>i4'),('','|V4'),('dval','>f8')]

Должно быть ясно, что любой структурированный тип можно описать с помощью этого интерфейса.

Отличия от интерфейса массива (Версия 2)

Интерфейс версии 2 был очень похож. Различия были в основном косметическими. В частности:

  1. Структура PyArrayInterface не имела члена descr в конце (и, следовательно, флага ARR_HAS_DESCR)
  2. Член desc объекта PyCObject, возвращаемого из __array_struct__, не был указан. Обычно это был объект, экспонирующий массив (чтобы можно было сохранить ссылку на него и уничтожить её при уничтожении объекта C). Теперь это должен быть кортеж, первым элементом которого является строка “PyArrayInterface Версия #”, а вторым — объект, экспонирующий массив.
  3. Кортеж, возвращаемый из __array_interface__[‘data’], раньше был шестнадцатеричной строкой (теперь это целое или длинное целое число).
  4. Атрибута __array_interface__ не было; вместо этого все ключи (кроме версии) в словаре __array_interface__ были собственными атрибутами: таким образом, чтобы получить информацию со стороны Python, вам нужно было отдельно получить доступ к атрибутам:
    • __array_data__
    • __array_shape__
    • __array_strides__
    • __array_typestr__
    • __array_descr__
    • __array_offset__
    • __array_mask__

© 2005–2019 NumPy Developers
Licensed under the 3-clause BSD License.
https://docs.scipy.org/doc/numpy-1.17.0/reference/arrays.interface.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API