Spec-Zone.ru › NumPy 1.12

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

Примечание

Эта страница описывает специфичный для numpy API для доступа к содержимому массива numpy из других расширений C. PEP 3118 – The Revised Buffer Protocol вводит аналогичный стандартизированный API для модулей расширения Python 2.6 и 3.0. Cython использует API PEP 3118 для работы с массивами буферов; см. учебник 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» (целое число Python — это C длинное целое число). Код, использующий этот атрибут, должен уметь обрабатывать это должным образом; либо поднимая ошибку, когда возможно переполнение, либо используя 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 Строка (фиксированная длина последовательности char)
U Unicode (фиксированная длина последовательности Py_UNICODE)
V Другое (void * — каждый элемент является фиксированным фрагментом памяти)

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

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

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

По умолчанию: [('', 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 или объект, экспонирующий интерфейс массива. Все элементы массива маски должны интерпретироваться только как true или не true, указывая, какие элементы этого массива действительны. Размеры этого объекта должны быть “broadcastable” размеру исходного массива.

По умолчанию: None (Все значения массива действительны)

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

Целое смещение в области данных массива. Это может быть использовано только тогда, когда data 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;

Член flags может состоять из 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__

© 2008–2017 NumPy Developers
Licensed under the NumPy License.
https://docs.scipy.org/doc/numpy-1.12.0/reference/arrays.interface.html

Spec-Zone.ru

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