Spec-Zone.ru › NumPy 1.11

Типы Python и C-структуры

В C-коде определены несколько новых типов. Большинство из них доступны из Python, но некоторые не экспонируются из-за ограниченного использования. Каждый новый тип Python имеет связанную PyObject * с внутренней структурой, которая включает указатель на «таблицу методов», определяющую, как новое объекту ведет себя в Python. Когда вы получаете объект Python в C-коде, вы всегда получаете указатель на структуру PyObject. Поскольку структура PyObject очень общая и определяет только PyObject_HEAD, сама по себе она не очень интересна. Однако разные объекты содержат больше деталей после PyObject_HEAD (но вам нужно привести к нужному типу, чтобы получить к ним доступ — или использовать функции-аксессоры или макросы).

Определенные новые типы Python

Типы Python — это функциональные эквиваленты в C классов в Python. Создавая новый тип Python, вы делаете доступным новый объект для Python. Объект ndarray является примером нового типа, определенного на C. Новые типы определяются на C двумя основными шагами:

  1. создание C-структуры (обычно с именем Py{Name}Object), которая бинарно совместима со структурой PyObject, но содержит дополнительную информацию, необходимую для данного объекта;
  2. заполнение таблицы PyTypeObject (на которую указывает член ob_type структуры PyObject) указателями на функции, которые реализуют желаемое поведение для типа.

Вместо специальных имён методов, которые определяют поведение для классов Python, существуют «таблицы функций», которые указывают на функции, которые реализуют желаемые результаты. Начиная с Python 2.2, сам PyTypeObject стал динамичным, что позволяет C-типам «подтипировать» другие C-типы на C и наследоваться от них в Python. Дочерние типы наследуют атрибуты и методы от своих родительских типов.

Существует два основных новых типа: ndarray ( PyArray_Type ) и ufunc ( PyUFunc_Type ). Дополнительные типы играют вспомогательную роль: PyArrayIter_Type, PyArrayMultiIter_Type, и PyArrayDescr_Type. PyArrayIter_Type — это тип плоского итератора для ndarray (объект, возвращаемый при получении атрибута flat). PyArrayMultiIter_Type — это тип объекта, возвращаемого при вызове broadcast (). Он обрабатывает итерацию и широковещание по набору вложенных последовательностей. Также PyArrayDescr_Type — это тип описателя типа данных, экземпляры которого описывают данные.

Наконец, есть 21 новый тип скаляров массивов, которые являются новыми скалярами Python, соответствующими каждому из основных типов данных, доступных для массивов. Еще 10 типов являются заглушками, которые позволяют скалярам массивов соответствовать иерархии фактических типов Python.

Тип PyArray_Type

PyArrayObject

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

typedef struct PyArrayObject {
    PyObject_HEAD
    char *data;
    int nd;
    npy_intp *dimensions;
    npy_intp *strides;
    PyObject *base;
    PyArray_Descr *descr;
    int flags;
    PyObject *weakreflist;
} PyArrayObject;
char *PyArrayObject.data

Указатель на первый элемент массива. Этот указатель можно (и обычно следует) привести к типу данных массива.

int PyArrayObject.nd

Целое число, определяющее количество измерений для этого массива. Когда nd равно 0, массив иногда называют массивом ранга 0. Такие массивы имеют неопределённые размеры и шаги и не могут быть обработаны. NPY_MAXDIMS — это максимальное количество измерений для любого массива.

npy_intp PyArrayObject.dimensions

Массив целых чисел, предоставляющий форму по каждому измерению, пока nd \geq 1. Целое число всегда достаточно велико, чтобы содержать указатель на платформе, поэтому размер измерения ограничен только памятью.

npy_intp *PyArrayObject.strides

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

PyObject *PyArrayObject.base

Этот член используется для хранения указателя на другой объект Python, связанный с этим массивом. Есть два варианта использования: 1) Если этот массив не владеет своей памятью, то base указывает на объект Python, который его владеет (возможно, другой объект массива), 2) Если у этого массива установлен флаг NPY_ARRAY_UPDATEIFCOPY, то этот массив является рабочей копией «неправильного» массива. Как только этот массив будет удален, массив, на который указывает base, будет обновлён содержимым этого массива.

PyArray_Descr *PyArrayObject.descr

Указатель на объект-описатель типа данных (см. ниже). Объект-описатель типа данных является экземпляром нового встроенного типа, который позволяет генерическое описание памяти. Для каждого поддерживаемого типа данных есть структура описателя. Эта структура описателя содержит полезную информацию о типе, а также указатель на таблицу указателей функций для реализации определённых функциональных возможностей.

int PyArrayObject.flags

Флаги, указывающие, как интерпретировать память, на которую указывает data. Возможные флаги — NPY_ARRAY_C_CONTIGUOUS, NPY_ARRAY_F_CONTIGUOUS, NPY_ARRAY_OWNDATA, NPY_ARRAY_ALIGNED, NPY_ARRAY_WRITEABLE и NPY_ARRAY_UPDATEIFCOPY.

PyObject *PyArrayObject.weakreflist

Этот член позволяет объектам массивов иметь слабые ссылки (используя модуль weakref).

Тип PyArrayDescr_Type

PyArray_Descr

Формат структуры PyArray_Descr, лежащей в основе PyArrayDescr_Type, выглядит следующим образом:

typedef struct {
    PyObject_HEAD
    PyTypeObject *typeobj;
    char kind;
    char type;
    char byteorder;
    char unused;
    int flags;
    int type_num;
    int elsize;
    int alignment;
    PyArray_ArrayDescr *subarray;
    PyObject *fields;
    PyArray_ArrFuncs *f;
} PyArray_Descr;
PyTypeObject *PyArray_Descr.typeobj

Указатель на тип объекта, который является соответствующим типом Python для элементов этого массива. Для встроенных типов, этот указатель указывает на соответствующий скаляр массива. Для типов, определенных пользователем, этот указатель должен указывать на тип объекта, определенный пользователем. Этот тип объекта может либо наследоваться от скаляров массива, либо нет. Если он не наследуется от скаляров массивов, то флаги NPY_USE_GETITEM и NPY_USE_SETITEM должны быть установлены в члене flags.

char PyArray_Descr.kind

Символьный код, указывающий на тип массива (используя обозначение типов строки интерфейса массива). ‘b’ представляет булевы значения, ‘i’ — целые со знаком, ‘u’ — целые без знака, ‘f’ — числа с плавающей точкой, ‘c’ — комплексные числа с плавающей точкой, ‘S’ — строка символов 8 бит, ‘U’ — строка символов Юникода 32 бит, а ‘V’ — произвольные.

char PyArray_Descr.type

Традиционный символьный код, указывающий на тип данных.

char PyArray_Descr.byteorder

Символ, указывающий порядок байтов: ‘>’ (big-endian), ‘<’ (little- endian), ‘=’ (native), ‘|’ (неважно, игнорировать). Все встроенные типы данных имеют порядок байтов ‘=’.

int PyArray_Descr.flags

Флаг типа данных, определяющий, демонстрирует ли тип данных поведение, подобное объектам массива. Каждый бит в этом члене является флагом, имеющим следующие названия:

PyDataType_FLAGCHK(PyArray_Descr *dtype, int flags)

Возвращает true, если все заданные флаги установлены для объекта типа данных.

PyDataType_REFCHK(PyArray_Descr *dtype)

Эквивалентно PyDataType_FLAGCHK (dtype, NPY_ITEM_REFCOUNT).

int PyArray_Descr.type_num

Число, которое однозначно идентифицирует тип данных. Для новых типов данных это число назначается при регистрации типа данных.

int PyArray_Descr.elsize

Для типов данных, размер которых всегда одинаковый (например, long), это значение содержит размер типа данных. Для гибких типов данных, где разные массивы могут иметь разный размер элемента, это значение должно быть 0.

int PyArray_Descr.alignment

Число, предоставляющее информацию об выравнивании для этого типа данных. В частности, оно показывает, насколько далеко от начала двумерной структуры (первым элементом которой является char ), компилятор помещает элемент этого типа: offsetof(struct {char c; type v;}, v)

PyArray_ArrayDescr *PyArray_Descr.subarray

Если это не NULL, то этот описатель типа данных — это C-стиль непрерывный массив другого описателя типа данных. Другими словами, каждый элемент, описываемый этим описателем, на самом деле является массивом некоторого другого базового описателя. Это наиболее полезно в качестве описателя типа данных для поля в другом описателе типа данных. Члены поля должны быть NULL если это не NULL (член поля базового описателя может быть не NULL). Структура PyArray_ArrayDescr определяется с помощью

typedef struct {
    PyArray_Descr *base;
    PyObject *shape;
} PyArray_ArrayDescr;

Элементы этой структуры:

PyArray_Descr *PyArray_ArrayDescr.base

Объект описателя типа данных базового типа.

PyObject *PyArray_ArrayDescr.shape

Форма (всегда непрерывная в стиле C) подмассива в виде кортежа Python.

PyObject *PyArray_Descr.fields

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

PyArray_ArrFuncs *PyArray_Descr.f

Указатель на структуру, содержащую функции, которые тип должен реализовывать для внутренних функций. Эти функции не являются тем же, что универсальные функции (ufuncs), описанные позже. Их подписи могут произвольно различаться.

PyArray_ArrFuncs

Функции, реализующие внутренние возможности. Не все эти указатели функций должны быть определены для данного типа. Требуемые члены — nonzero, copyswap, copyswapn, setitem, getitem, и cast. Предполагается, что они не NULL и NULL записи приведут к сбою программы. Другие функции могут быть NULL, что просто означает уменьшенную функциональность для этого типа данных. (Также функция nonzero будет заполнена по умолчанию, если она NULL при регистрации пользовательского типа данных).

typedef struct {
    PyArray_VectorUnaryFunc *cast[NPY_NTYPES];
    PyArray_GetItemFunc *getitem;
    PyArray_SetItemFunc *setitem;
    PyArray_CopySwapNFunc *copyswapn;
    PyArray_CopySwapFunc *copyswap;
    PyArray_CompareFunc *compare;
    PyArray_ArgFunc *argmax;
    PyArray_DotFunc *dotfunc;
    PyArray_ScanFunc *scanfunc;
    PyArray_FromStrFunc *fromstr;
    PyArray_NonzeroFunc *nonzero;
    PyArray_FillFunc *fill;
    PyArray_FillWithScalarFunc *fillwithscalar;
    PyArray_SortFunc *sort[NPY_NSORTS];
    PyArray_ArgSortFunc *argsort[NPY_NSORTS];
    PyObject *castdict;
    PyArray_ScalarKindFunc *scalarkind;
    int **cancastscalarkindto;
    int *cancastto;
    PyArray_FastClipFunc *fastclip;
    PyArray_FastPutmaskFunc *fastputmask;
    PyArray_FastTakeFunc *fasttake;
    PyArray_ArgFunc *argmin;
} PyArray_ArrFuncs;

В описании указателей функций используется понятие корректного сегмента. Корректный сегмент выровнен и находится в родном порядке байтов для данного типа данных. Функции nonzero, copyswap, copyswapn, getitem, и setitem могут (и должны) обрабатывать некорректные массивы. Другие функции требуют корректных сегментов памяти.

void cast(void *from, void *to, npy_intp n, void *fromarr, void *toarr)

Массив указателей функций для преобразования из текущего типа во все другие встроенные типы. Каждая функция преобразует непрерывный, выровненный и не инвертированный буфер, указанный в from, в непрерывный, выровненный и не инвертированный буфер, указанный в to. Количество элементов для преобразования задаётся n, а аргументы fromarr и toarr интерпретируются как PyArrayObjects для гибких массивов, чтобы получить информацию о размере элемента.

PyObject *getitem(void *data, void *arr)

Указатель на функцию, которая возвращает стандартный объект Python из одного элемента объекта массива arr, на который указывает data. Эта функция должна уметь правильно обрабатывать «неправильные» (невыровненные и/или инвертированные) массивы.

int setitem(PyObject *item, void *data, void *arr)

Указатель на функцию, которая устанавливает объект Python item в массив arr в позиции, на которую указывает data. Эта функция обрабатывает «неправильные» массивы. При успешном выполнении возвращается ноль, в противном случае — минус один (и устанавливается ошибка Python).

void copyswapn(void *dest, npy_intp dstride, void *src, npy_intp sstride, npy_intp n, int swap, void *arr)
void copyswap(void *dest, void *src, int swap, void *arr)

Эти члены являются указателями на функции для копирования данных из src в dest и, если указано, их инвертирования. Значение arr используется только для гибких ( NPY_STRING, NPY_UNICODE и NPY_VOID ) массивов (и получается из arr->descr->elsize ). Вторая функция копирует одно значение, а первая проходит по n значениям с предоставленными шагами. Эти функции могут обрабатывать некорректные данные src. Если src равен NULL, то копирование не выполняется. Если swap равен 0, то инвертирование байтов не происходит. Предполагается, что dest и src не перекрываются. Если они перекрываются, то сначала используйте memmove (...), а затем copyswap(n) с нулевым значением src.

int compare(const void* d1, const void* d2, void* arr)

Указатель на функцию, которая сравнивает два элемента массива, arr, указанных d1 и d2. Эта функция требует корректных (выровненных и не инвертированных) массивов. Возвращаемое значение равно 1, если * d1 > * d2, 0, если * d1 == * d2, и -1, если * d1 < * d2. Объект массива arr используется для получения размера элемента и информации о поле для гибких массивов.

int argmax(void* data, npy_intp n, npy_intp* max_ind, void* arr)

Указатель на функцию, которая получает индекс наибольшего из n элементов в arr, начиная с элемента, на который указывает data. Эта функция требует, чтобы сегмент памяти был непрерывным и корректным. Возвращаемое значение всегда 0. Индекс наибольшего элемента возвращается в max_ind.

void dotfunc(void* ip1, npy_intp is1, void* ip2, npy_intp is2, void* op, npy_intp n, void* arr)

Указатель на функцию, которая перемножает две n-длинные последовательности, складывает их и помещает результат в элемент, на который указывает op в arr. Начало двух последовательностей указано в ip1 и ip2. Для перехода к следующему элементу в каждой последовательности требуется переход на is1 и is2 байтов, соответственно. Эта функция требует корректной (хотя и не обязательно непрерывной) памяти.

int scanfunc(FILE* fd, void* ip, void* sep, void* arr)

Указатель на функцию, которая сканирует (в стиле scanf) один элемент соответствующего типа из дескриптора файла fd в память массива, на которую указывает ip. Массив предполагается корректным. Если sep не равен NULL, то перед возвратом также сканируется разделительная строка из файла. Последний аргумент arr — массив, в который выполняется сканирование. Возвращается 0, если сканирование выполнено успешно. Отрицательное число указывает на проблему: -1 означает, что конец файла был достигнут до сканирования разделительной строки, -4 означает, что конец файла был достигнут до сканирования элемента, а -3 означает, что элемент не может быть интерпретирован из строки формата. Требуется корректный массив.

int fromstr(char* str, void* ip, char** endptr, void* arr)

Указатель на функцию, которая преобразует строку, на которую указывает str, в один элемент соответствующего типа и помещает его в место памяти, на которое указывает ip. После завершения преобразования *endptr указывает на оставшуюся часть строки. Последний аргумент arr — массив, в который ip указывает (необходимый для массивов переменного размера).

Bool nonzero(void* data, void* arr)

Указатель на функцию, которая возвращает TRUE, если элемент arr, на который указывает data, не равен нулю. Эта функция может обрабатывать некорректные массивы.

void fill(void* data, npy_intp length, void* arr)

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

void fillwithscalar(void* buffer, npy_intp length, void* value, void* arr)

Указатель на функцию, которая заполняет непрерывный buffer заданного length одним скалярным value, адрес которого задан. Последний аргумент — массив, необходимый для получения размера элемента для массивов переменной длины.

int sort(void* start, npy_intp length, void* arr)

Массив указателей функций к определенному алгоритму сортировки. Определённый алгоритм сортировки получается с помощью ключа (на данный момент NPY_QUICKSORT, :data`NPY_HEAPSORT`, и NPY_MERGESORT определены). Эти сортировки выполняются на месте, предполагая непрерывные и выровненные данные.

int argsort(void* start, npy_intp* result, npy_intp length, void *arr)

Массив указателей функций на алгоритмы сортировки для этого типа данных. Доступны те же алгоритмы сортировки, что и для sort. Индексы, дающие сортировку, возвращаются в result (который должен быть инициализирован индексами от 0 до length-1 включительно).

PyObject *castdict

Либо NULL, либо словарь, содержащий низкоуровневые функции преобразования для пользовательских типов данных. Каждая функция обернута в PyCObject * и индексирована по номеру типа данных.

NPY_SCALARKIND scalarkind(PyArrayObject* arr)

Функция для определения того, как следует интерпретировать скаляры этого типа. Аргумент — NULL или одномерный массив, содержащий данные (если это необходимо для определения типа скаляра). Возвращаемое значение должно быть типа NPY_SCALARKIND.

int **cancastscalarkindto

Либо NULL, либо массив указателей NPY_NSCALARKINDS. Эти указатели должны быть либо NULL, либо указателем на массив целых чисел (завершаемый NPY_NOTYPE), указывающий на типы данных, в которые скаляр этого типа указанного типа может быть безопасно преобразован (обычно это означает без потери точности).

int *cancastto

Либо NULL, либо массив целых чисел (завершаемый NPY_NOTYPE ), указывающий на типы данных, в которые этот тип данных может быть безопасно преобразован (обычно это означает без потери точности).

void fastclip(void *in, npy_intp n_in, void *min, void *max, void *out)

Функция, которая считывает n_in элементов из in, и записывает в out значение, которое считывается, если оно находится в пределах, указанных min и max, или соответствующее предел, если оно вне. Сегменты памяти должны быть непрерывными и корректными, и либо min или max может быть NULL, но не оба.

void fastputmask(void *in, void *mask, npy_intp n_in, void *values, npy_intp nv)

Функция, которая принимает указатель in на массив n_in элементов, указатель mask на массив n_in логических значений и указатель vals на массив nv элементов. Элементы из vals копируются в in, где значение в mask не равно нулю, масштабируя vals, если nv < n_in. Все массивы должны быть непрерывными и корректными.

void fasttake(void *dest, void *src, npy_intp *indarray, npy_intp nindarray, npy_intp n_outer, npy_intp m_middle, npy_intp nelem, NPY_CLIPMODE clipmode)

Функция, которая берет указатель src на непрерывный, корректный сегмент памяти, интерпретируемый как трехмерный массив формы (n_outer, nindarray, nelem), указатель indarray на непрерывный, корректный сегмент целых индексов, и указатель dest на непрерывный, корректный сегмент памяти, интерпретируемый как трехмерный массив формы (n_outer, m_middle, nelem). Индексы в indarray используются для индексирования src по второму измерению и копирования соответствующих блоков из nelem элементов в dest. clipmode (которое может принимать значения NPY_RAISE, NPY_WRAP или NPY_CLIP) определяет, как будут обрабатываться индексы, меньшие 0 или большие, чем nindarray.

int argmin(void* data, npy_intp n, npy_intp* min_ind, void* arr)

Указатель на функцию, которая извлекает индекс наименьшего из n элементов в arr, начиная с элемента, на который указывает data. Эта функция требует, чтобы сегмент памяти был непрерывным и корректным. Возвращаемое значение всегда 0. Индекс наименьшего элемента возвращается в min_ind.

Тип PyArray_Type реализует многие особенности объектов Python, включая интерфейсы tp_as_number, tp_as_sequence, tp_as_mapping и tp_as_buffer. Также используется богатая сравнимость (tp_richcompare), а также поиск атрибутов нового стиля для методов (tp_methods) и свойств (tp_getset). Тип PyArray_Type также может быть подтипизирован.

Подсказка

Методы tp_as_number используют универсальный подход для вызова любой функции, которая была зарегистрирована для обработки операции. Функция PyNumeric_SetOps(..) может быть использована для регистрации функций для обработки конкретных математических операций (для всех массивов). При импорте модуля umath он устанавливает числовые операции для всех массивов на соответствующие ufuncs. Методы tp_str и tp_repr также могут быть изменены с помощью PyString_SetStringFunction(...).

PyUFunc_Type

PyUFuncObject

Ядром ufunc является PyUFuncObject, который содержит всю информацию, необходимую для вызова подлежащих C-кодовых циклов, выполняющих фактическую работу. Он имеет следующую структуру:

typedef struct {
    PyObject_HEAD
    int nin;
    int nout;
    int nargs;
    int identity;
    PyUFuncGenericFunction *functions;
    void **data;
    int ntypes;
    int reserved1;
    const char *name;
    char *types;
    const char *doc;
    void *ptr;
    PyObject *obj;
    PyObject *userloops;
    npy_uint32 *op_flags;
    npy_uint32 *iter_flags;
} PyUFuncObject;
int PyUFuncObject.nin

Количество входных аргументов.

int PyUFuncObject.nout

Количество выходных аргументов.

int PyUFuncObject.nargs

Общее количество аргументов (nin + nout). Это значение должно быть меньше NPY_MAXARGS.

int PyUFuncObject.identity

Либо PyUFunc_One, PyUFunc_Zero, или PyUFunc_None для указания тождества для данной операции. Используется только для вызова reduce-подобного метода на пустом массиве.

void PyUFuncObject.functions(char** args, npy_intp* dims,
npy_intp* steps, void* extradata)

Массив указателей на функции — по одному для каждого типа данных, поддерживаемого ufunc. Это векторный цикл, который вызывается для реализации подлежащей функции dims [0] раз. Первый аргумент, args, представляет собой массив из nargs указателей на сегменты памяти. Указатели на данные для входных аргументов находятся первыми, за которыми следуют указатели на данные для выходных аргументов. Количество байтов, которое нужно пропустить, чтобы получить следующий элемент в последовательности, задается соответствующей записью в массиве steps. Последний аргумент позволяет циклу получать дополнительную информацию. Это часто используется для того, чтобы один общий векторный цикл можно было использовать для нескольких функций. В этом случае фактическая скалярная функция для вызова передаётся как extradata. Размер этого массива указателей на функции равен ntypes.

void **PyUFuncObject.data

Дополнительные данные, которые передаются в 1-мерные векторные циклы, или NULL если дополнительные данные не нужны. Этот массив C должен иметь тот же размер (т.е. ntypes), что и массив функций. NULL используется, если дополнительные данные не нужны. Несколько вызовов C-API для UFuncs — это просто 1-мерные векторные циклы, которые используют эти дополнительные данные для получения указателя на фактическую вызываемую функцию.

int PyUFuncObject.ntypes

Количество поддерживаемых типов данных для ufunc. Это число определяет количество различных 1-мерных циклов (встроенных типов данных), которые доступны.

char *PyUFuncObject.name

Строковое имя для ufunc. Используется динамически для построения атрибута __doc__ ufuncs.

char *PyUFuncObject.types

Массив из nargs \times ntypes 8-битовых type_numbers, который содержит сигнатуру типа для функции для каждого из поддерживаемых (встроенных) типов данных. Для каждой из ntypes функций соответствующий набор type_numbers в этом массиве показывает, как аргумент args должен быть интерпретирован в 1-мерном векторном цикле. Эти типы чисел не должны быть одинаковыми, и поддерживаются ufuncs смешанных типов.

char *PyUFuncObject.doc

Документация для ufunc. Не должна содержать сигнатуры функции, так как она генерируется динамически при получении атрибута __doc__.

void *PyUFuncObject.ptr

Любая динамически выделенная память. В настоящее время используется для динамических ufuncs, созданных из функции python, для хранения места для членов types, data и name.

PyObject *PyUFuncObject.obj

Для ufuncs, динамически созданных из функций python, этот член хранит ссылку на базовую функцию Python.

PyObject *PyUFuncObject.userloops

Словарь пользовательских 1-мерных векторных циклов (хранится как указатели CObject) для пользовательских типов. Пользователь может зарегистрировать цикл для любого пользовательского типа. Он извлекается по номеру типа. Номера типов пользователей всегда больше, чем NPY_USERDEF.

npy_uint32 PyUFuncObject.op_flags

Переопределяет флаги операндов по умолчанию для каждого операнда ufunc.

npy_uint32 PyUFuncObject.iter_flags

Переопределяет флаги nditer по умолчанию для ufunc.

PyArrayIter_Type

PyArrayIterObject

Структура C, соответствующая объекту PyArrayIter_Type — это PyArrayIterObject. PyArrayIterObject используется для отслеживания указателя в N-мерном массиве. Он содержит связанную информацию, используемую для быстрого перемещения по массиву. Указатель может быть изменён тремя основными способами: 1) перейти к следующей позиции в массиве в стиле C-стиля, 2) перейти к произвольной N-мерной координате в массиве и 3) перейти к произвольному одномерному индексу в массиве. Члены структуры PyArrayIterObject используются в этих вычислениях. Объекты-итераторы сохраняют свои собственные размерности и шаги массива. Это можно изменять по мере необходимости для «вещания» или для перебора только определённых измерений.

typedef struct {
    PyObject_HEAD
    int   nd_m1;
    npy_intp  index;
    npy_intp  size;
    npy_intp  coordinates[NPY_MAXDIMS];
    npy_intp  dims_m1[NPY_MAXDIMS];
    npy_intp  strides[NPY_MAXDIMS];
    npy_intp  backstrides[NPY_MAXDIMS];
    npy_intp  factors[NPY_MAXDIMS];
    PyArrayObject *ao;
    char  *dataptr;
    Bool  contiguous;
} PyArrayIterObject;
int PyArrayIterObject.nd_m1

N-1, где N — количество измерений в базовом массиве.

npy_intp PyArrayIterObject.index

Текущий одномерный индекс в массиве.

npy_intp PyArrayIterObject.size

Общий размер базового массива.

npy_intp *PyArrayIterObject.coordinates

N-мерный индекс в массиве.

npy_intp *PyArrayIterObject.dims_m1

Размер массива минус 1 в каждом измерении.

npy_intp *PyArrayIterObject.strides

Шаги массива. Сколько байт нужно перейти, чтобы перейти к следующему элементу в каждом измерении.

npy_intp *PyArrayIterObject.backstrides

Сколько байт нужно перейти, чтобы перейти от конца измерения к его началу. Обратите внимание, что backstrides[k] = strides[k]*dims_m1[k], но оно хранится здесь для оптимизации.

npy_intp *PyArrayIterObject.factors

Этот массив используется для вычисления N-мерного индекса из одномерного индекса. Он содержит необходимые произведения измерений.

PyArrayObject *PyArrayIterObject.ao

Указатель на базовый ndarray, для представления которого был создан этот итератор.

char *PyArrayIterObject.dataptr

Этот член указывает на элемент в ndarray, указанный индексом.

Bool PyArrayIterObject.contiguous

Флаг, равный true, если базовый массив является NPY_ARRAY_C_CONTIGUOUS. Используется для упрощения вычислений, когда это возможно.

Более подробное объяснение использования итератора массива на уровне C приведено в последующих разделах. Обычно вам не нужно беспокоиться о внутренней структуре объекта-итератора и взаимодействовать с ним только через макросы PyArray_ITER_NEXT (it), PyArray_ITER_GOTO (it, dest) или PyArray_ITER_GOTO1D (it, index). Все эти макросы требуют аргумент it, являющийся объектом PyArrayIterObject *.

PyArrayMultiIter_Type

PyArrayMultiIterObject
typedef struct {
    PyObject_HEAD
    int numiter;
    npy_intp size;
    npy_intp index;
    int nd;
    npy_intp dimensions[NPY_MAXDIMS];
    PyArrayIterObject *iters[NPY_MAXDIMS];
} PyArrayMultiIterObject;
int PyArrayMultiIterObject.numiter

Количество массивов, которые необходимо «вещать» до одинаковой формы.

npy_intp PyArrayMultiIterObject.size

Общий размер после вещания.

npy_intp PyArrayMultiIterObject.index

Текущий (одномерный) индекс в результате вещания.

int PyArrayMultiIterObject.nd

Количество измерений в результате вещания.

npy_intp *PyArrayMultiIterObject.dimensions

Форма результата вещания (используются только nd слоты).

PyArrayIterObject **PyArrayMultiIterObject.iters

Массив объектов-итераторов, содержащий итераторы для массивов, которые нужно «вещать» вместе. При возвращении итераторы корректируются для вещания.

PyArrayNeighborhoodIter_Type

PyArrayNeighborhoodIterObject

Структура C, соответствующая объекту PyArrayNeighborhoodIter_Type — это PyArrayNeighborhoodIterObject.

PyArrayFlags_Type

Типы скалярных массивов

Для каждого из различных встроенных типов данных, которые могут присутствовать в массиве, существует Python-тип. Большинство из них являются простыми оболочками над соответствующим типом данных в C. Имена C для этих типов — Py{TYPE}ArrType_Type , где {TYPE} может быть

Bool, Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong, ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble, String, Unicode, Void и Object.

Эти имена типов являются частью C-API и могут быть созданы в расширенном C-коде. Также есть PyIntpArrType_Type и PyUIntpArrType_Type, которые являются простыми заменами одного из целочисленных типов, которые могут содержать указатель на платформе. Структура этих скалярных объектов не раскрывается C-коду. Функция PyArray_ScalarAsCtype (..) может использоваться для извлечения значения типа C из скаляра массива, а функция PyArray_Scalar (...) может использоваться для создания скаляра массива из C-значения.

Другие структуры C

Несколько новых структур C оказались полезными при разработке NumPy. Эти структуры C используются по крайней мере в одном вызове C-API и поэтому документированы здесь. Основная причина определения этих структур — упрощение использования Python ParseTuple C-API для преобразования из Python-объектов в полезный C-объект.

PyArray_Dims

PyArray_Dims

Эта структура очень полезна, когда ожидается интерпретация информации о форме и/или шагах. Структура:

typedef struct {
    npy_intp *ptr;
    int len;
} PyArray_Dims;

Члены этой структуры:

npy_intp *PyArray_Dims.ptr

Указатель на список (npy_intp) целых чисел, которые обычно представляют форму массива или шаги массива.

int PyArray_Dims.len

Длина списка целых чисел. Предполагается, что доступ к ptr[0] до ptr[len-1] безопасен.

PyArray_Chunk

PyArray_Chunk

Это эквивалентно структуре объекта буфера в Python до члена ptr. На 32-битных платформах (т.е., если NPY_SIZEOF_INT == NPY_SIZEOF_INTP), член len также соответствует эквивалентному члену объекта буфера. Полезно для представления общего сегмента памяти.

typedef struct {
    PyObject_HEAD
    PyObject *base;
    void *ptr;
    npy_intp len;
    int flags;
} PyArray_Chunk;

Члены:

PyObject *PyArray_Chunk.base

Python-объект, из которого получен этот сегмент памяти. Необходим для правильного учёта памяти.

void *PyArray_Chunk.ptr

Указатель на начало сегмента памяти.

npy_intp PyArray_Chunk.len

Длина сегмента в байтах.

int PyArray_Chunk.flags

Любые флаги данных (например, NPY_ARRAY_WRITEABLE), которые должны использоваться для интерпретации памяти.

PyArrayInterface

См. также

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

PyArrayInterface

Структура PyArrayInterface определена для того, чтобы NumPy и другие модули расширения могли использовать протокол быстрого интерфейса массивов. Метод __array_struct__ объекта, поддерживающего протокол быстрого интерфейса массивов, должен возвращать PyCObject, который содержит указатель на структуру PyArrayInterface с соответствующими деталями массива. После создания нового массива атрибут должен быть DECREF’d, что освободит структуру PyArrayInterface. Не забудьте INCREF объект (чьё значение атрибута __array_struct__ было получено) и установить базовое значение нового PyArrayObject на этот же объект. Таким образом, память для массива будет управляться корректно.

typedef struct {
    int two;
    int nd;
    char typekind;
    int itemsize;
    int flags;
    npy_intp *shape;
    npy_intp *strides;
    void *data;
    PyObject *descr;
} PyArrayInterface;
int PyArrayInterface.two

целое число 2 в качестве проверки.

int PyArrayInterface.nd

количество измерений в массиве.

char PyArrayInterface.typekind

Символ, указывающий на тип массива в соответствии с соглашением типов, с ‘t’ -> битовое поле, ‘b’ -> булево, ‘i’ -> целое со знаком, ‘u’ -> целое без знака, ‘f’ -> число с плавающей точкой, ‘c’ -> комплексное число с плавающей точкой, ‘O’ -> объект, ‘S’ -> (байтовый) строка, ‘U’ -> юникод, ‘V’ -> пустое.

int PyArrayInterface.itemsize

Количество байтов, необходимых для каждого элемента в массиве.

int PyArrayInterface.flags

Любой из битов NPY_ARRAY_C_CONTIGUOUS (1), NPY_ARRAY_F_CONTIGUOUS (2), NPY_ARRAY_ALIGNED (0x100), NPY_ARRAY_NOTSWAPPED (0x200) или NPY_ARRAY_WRITEABLE (0x400) для указания информации о данных. Флаги NPY_ARRAY_ALIGNED, NPY_ARRAY_C_CONTIGUOUS и NPY_ARRAY_F_CONTIGUOUS фактически могут быть определены из других параметров. Флаг NPY_ARR_HAS_DESCR (0x800) также может быть установлен, чтобы указать объектам, использующим интерфейс массива версии 3, что член descr структуры присутствует (он будет проигнорирован объектами, использующими интерфейс массива версии 2).

npy_intp *PyArrayInterface.shape

Массив, содержащий размер массива в каждом измерении.

npy_intp *PyArrayInterface.strides

Массив, содержащий количество байтов, которое нужно пропустить, чтобы получить следующий элемент в каждом измерении.

void *PyArrayInterface.data

Указатель на первый элемент массива.

PyObject *PyArrayInterface.descr

Объект Python, описывающий тип данных более подробно (такой же, как ключ descr в __array_interface__). Он может быть NULL если typekind и itemsize предоставляют достаточно информации. Этот поле также игнорируется, если флаг ARR_HAS_DESCR установлен в flags.

Внутренние используемые структуры

Внутренне код использует некоторые дополнительные объекты Python, в основном для управления памятью. Эти типы недоступны напрямую из Python и не экспонируются в C-API. Они включены сюда только для полноты и для помощи в понимании кода.

PyUFuncLoopObject

Слабый оболочкой для C-структуры, содержащей информацию, необходимую для циклов. Это полезно, если вы пытаетесь понять код циклов ufunc. PyUFuncLoopObject — это связанная C-структура. Она определена в заголовке ufuncobject.h.

PyUFuncReduceObject

Слабый оболочкой для C-структуры, содержащей информацию, необходимую для методов reduce-подобных ufunc. Это полезно, если вы пытаетесь понять код reduce, accumulate и reduce-at. PyUFuncReduceObject — это связанная C-структура. Она определена в заголовке ufuncobject.h.

PyUFunc_Loop1d

Простая связанная цепь C-структур, содержащих информацию, необходимую для определения цикла 1-d для ufunc для каждой определенной подписи пользовательского типа данных.

© 2008–2016 NumPy Developers
Licensed under the NumPy License.
https://docs.scipy.org/doc/numpy-1.11.0/reference/c-api.types-and-structures.html

Spec-Zone.ru

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