Типы Python и C-структуры
В коде на C определено несколько новых типов. Большинство из них доступны из Python, но некоторые не экспонируются из-за ограниченного использования. Каждый новый тип Python связан с PyObject * структурой, содержащей внутреннюю структуру, которая включает указатель на «таблицу методов», определяющую поведение нового объекта в Python. При получении объекта Python в код C вы всегда получаете указатель на структуру PyObject. Поскольку структура PyObject очень общая и определяет только PyObject_HEAD, сама по себе она не очень интересна. Однако разные объекты содержат больше деталей после PyObject_HEAD (но вы должны выполнить приведение к правильному типу, чтобы получить к ним доступ — или использовать функции-обработчики или макросы).
Определённые новые типы Python
Типы Python — это функциональные эквиваленты классов в Python на C. Создавая новый тип Python, вы делаете доступным новый объект для Python. Объект ndarray является примером нового типа, определённого на C. Новые типы определяются на C двумя основными шагами:
- создание C-структуры (обычно с именем
Py{Name}Object), которая совместима сPyObjectструктурой, но содержит дополнительную информацию, необходимую для этого конкретного объекта; - заполнение таблицы
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 — это тип описателя типа данных, экземпляры которого описывают данные.
PyArray_Type и PyArrayObject
-
PyArray_Type -
Тип Python для ndarray —
PyArray_Type. В C каждый ndarray — это указатель на структуруPyArrayObject. Член ob_type этой структуры содержит указатель на тип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;
-
PyArrayObject.PyObject_HEAD -
Это необходимо для всех объектов Python. Она состоит (по крайней мере) из члена счётчика ссылок (
ob_refcnt) и указателя на тип объекта (ob_type). (Другие элементы также могут быть присутствовать, если Python был скомпилирован со специальными опциями. См. Include/object.h в дереве исходных кодов Python для получения дополнительной информации). Член ob_type указывает на объект типа Python.
-
char *PyArrayObject.data -
Указатель на первый элемент массива. Этот указатель можно (и обычно следует) преобразовать к типу данных массива.
-
int PyArrayObject.nd -
Целое число, определяющее количество измерений для этого массива. Когда nd равно 0, массив иногда называют массивом ранга 0. Такие массивы имеют неопределённые размеры и шаги и не могут быть обработаны.
NPY_MAXDIMS— это максимальное количество измерений для любого массива.
-
npy_intp PyArrayObject.dimensions -
Массив целых чисел, задающий форму в каждом измерении, пока nd
1. Целое число всегда достаточно велико, чтобы содержать указатель на платформе, поэтому размер измерения ограничен только памятью.
-
npy_intp *PyArrayObject.strides -
Массив целых чисел, определяющий для каждого измерения количество байтов, которые необходимо пропустить, чтобы перейти к следующему элементу в этом измерении.
-
PyObject *PyArrayObject.base -
Этот член используется для хранения указателя на другой объект Python, связанный с этим массивом. Есть два случая использования:
- Если этот массив не владеет своей памятью, то base указывает на объект Python, который им владеет (возможно, другой объект массива)
- Если для этого массива установлен флаг (устаревший)
NPY_ARRAY_UPDATEIFCOPYилиNPY_ARRAY_WRITEBACKIFCOPY, то этот массив является рабочей копией «неправильного» массива.
При вызове
PyArray_ResolveWritebackIfCopy, массив, на который указывает 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_WRITEBACKIFCOPYиNPY_ARRAY_UPDATEIFCOPY.
-
PyObject *PyArrayObject.weakreflist -
Этот член позволяет объектам массива иметь слабые ссылки (используя модуль weakref).
PyArrayDescr_Type и PyArray_Descr
-
PyArrayDescr_Type -
PyArrayDescr_Type— это встроенный тип объектов описателя типа данных, используемых для описания способов интерпретации байтов, составляющих массив. Существует 21 статически определённый объектPyArray_Descrдля встроенных типов данных. Хотя они участвуют в подсчёте ссылок, их счётчик ссылок никогда не должен достигать нуля. Также поддерживается динамическая таблица пользовательских объектовPyArray_Descr. После «регистрации» объекта описателя типа данных его не следует удалять. ФункцияPyArray_DescrFromType(…) может использоваться для получения объектаPyArray_Descrиз перечисленного номера типа (встроенного или пользовательского).
-
PyArray_Descr -
Структура
PyArray_Descrлежит в основеPyArrayDescr_Type. Хотя она описана здесь для полноты, её следует считать внутренней для NumPy и манипулировать с помощью функций и макросовPyArrayDescr_*илиPyDataType*. Размер этой структуры может меняться в разных версиях NumPy. Для обеспечения совместимости:- Никогда не объявляйте экземпляр структуры, не являющейся указателем.
- Никогда не выполняйте арифметические операции с указателями.
- Никогда не используйте
sizof(PyArray_Descr)
Она имеет следующую структуру:
typedef struct { PyObject_HEAD PyTypeObject *typeobj; char kind; char type; char byteorder; char flags; int type_num; int elsize; int alignment; PyArray_ArrayDescr *subarray; PyObject *fields; PyObject *names; PyArray_ArrFuncs *f; PyObject *metadata; NpyAuxData *c_metadata; npy_hash_t hash; } 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 -
Символ, указывающий порядок байтов: ‘>’ (большая эндианность), ‘<’ (малая эндианность), ‘=’ (родная), ‘|’ (не имеет значения, игнорировать). Все встроенные типы данных имеют порядок байтов ‘=’.
-
char PyArray_Descr.flags -
Флаги типа данных, определяющие, демонстрирует ли тип данных поведение массива объектов. Каждый бит в этом члене является флагом, которые названы как:
-
NPY_ITEM_REFCOUNT -
Указывает, что элементы этого типа данных должны быть учтены в счетчике ссылок (используя
Py_INCREFиPy_DECREF).
-
NPY_ITEM_HASOBJECT -
То же, что и
NPY_ITEM_REFCOUNT.
-
NPY_LIST_PICKLE -
Указывает, что массивы этого типа данных должны быть преобразованы в список перед сериализацией.
-
NPY_ITEM_IS_POINTER -
Указывает, что элемент является указателем на другой тип данных.
-
NPY_NEEDS_INIT -
Указывает, что память для этого типа данных должна быть инициализирована (установлена в 0) при создании.
-
NPY_NEEDS_PYAPI -
Указывает, что этому типу данных требуется Python C-API во время доступа (так что не отпускайте GIL, если будет необходим доступ к массиву).
-
NPY_USE_GETITEM -
При доступе к массиву используйте указатель на функцию
f->getitemвместо стандартного преобразования в массив скаляров. Необходимо использовать, если вы не определяете массив скаляров, соответствующий типу данных.
-
NPY_USE_SETITEM -
При создании 0-мерного массива из массива скаляров используйте
f->setitemвместо стандартной копии из массива скаляров. Необходимо использовать, если вы не определяете массив скаляров, соответствующий типу данных.
-
NPY_FROM_FIELDS -
Биты, унаследованные от родительского типа данных, если эти биты установлены в любом поле типа данных. В настоящее время (
NPY_NEEDS_INIT|NPY_LIST_PICKLE|NPY_ITEM_REFCOUNT|NPY_NEEDS_PYAPI).
-
NPY_OBJECT_DTYPE_FLAGS -
Биты, установленные для типа данных объекта: (
NPY_LIST_PICKLE|NPY_USE_GETITEM|NPY_ITEM_IS_POINTER|NPY_REFCOUNT|NPY_NEEDS_INIT|NPY_NEEDS_PYAPI).
-
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-стиля, расположенный по соседству, другого дескриптора типа данных. Другими словами, каждый элемент, описываемый этим дескриптором, фактически является массивом некоторого другого базового дескриптора. Это наиболее полезно в качестве дескриптора типа данных для поля в другом дескрипторе типа данных. Член fields должен бытьNULLесли это неNULL(член fields базового дескриптора может быть не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. Эти кортежи помещаются в этот словарь с ключом по имени (а также по заголовку, если указан).
-
PyObject *PyArray_Descr.names -
Упорядоченный кортеж имён полей. Он равен NULL, если поля не определены.
-
PyArray_ArrFuncs *PyArray_Descr.f -
Указатель на структуру, содержащую функции, которые тип должен реализовывать для внутренних функций. Эти функции не являются теми же, что универсальные функции (ufuncs), описанные ниже. Их сигнатуры могут быть произвольными.
-
PyObject *PyArray_Descr.metadata -
Метаданные об этом dtype.
-
NpyAuxData *PyArray_Descr.c_metadata -
Метаданные, специфичные для реализации dtype на C. Добавлен для NumPy 1.7.0.
-
Npy_hash_t *PyArray_Descr.hash -
В настоящее время не используется. Зарезервирован для использования в будущем для кэширования значений хеша.
-
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 и swap, если это указано. Значение arr используется только для гибких (
NPY_STRING,NPY_UNICODEиNPY_VOID) массивов (и получается изarr->descr->elsize). Вторая функция копирует одно значение, а первая повторяется по n значениям с заданными шагами. Эти функции могут обрабатывать некорректные данные src. Если src равен NULL, то копирование не выполняется. Если swap равен 0, то перестановка байтов не происходит. Предполагается, что dest и src не перекрываются. Если они перекрываются, то сначала используйтеmemmove(…), а затемcopyswap(n)сsrcравным NULL.
-
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* arr) -
Указатель на функцию, которая сканирует (в стиле scanf) один элемент соответствующего типа из дескриптора файла
fdв память массива, на которую указываетip. Массив предполагается правильным. Последний аргументarr— массив, в который будет производиться сканирование. Возвращает количество успешно присвоенных аргументов приема (что может быть нулём в случае неудачи при сопоставлении перед присвоением первого аргумента приема) или EOF, если происходит ошибка входных данных до присвоения первого аргумента приема. Эта функция должна вызываться без удержания Python GIL, и должна захватить его для отчётности об ошибках.
-
int fromstr(char* str, void* ip, char** endptr, void* arr) -
Указатель на функцию, которая преобразует строку, на которую указывает
str, в один элемент соответствующего типа и помещает его в место памяти, на которое указываетip. После завершения преобразования*endptrуказывает на остаток строки. Последний аргументarr— массив, в который указывает ip (необходим для массивов переменного размера). Возвращает 0 при успехе или -1 при ошибке. Требует правильный массив. Эта функция должна вызываться без удержания Python GIL, и должна захватить его для отчётности об ошибках.
-
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,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на непрерывный, ведомый сегмент, интерпретируемый как 3-мерный массив формы(n_outer, nindarray, nelem), указательindarrayна непрерывный, ведомый сегментm_middleцелочисленных индексов и указательdestна непрерывный, ведомый сегмент, интерпретируемый как 3-мерный массив формы(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 objects, включая интерфейсы tp_as_number, tp_as_sequence, tp_as_mapping и tp_as_buffer. Также используется rich comparison совместно с поиском атрибутов нового стиля для членов (tp_members) и свойств (tp_getset). Тип PyArray_Type также может быть подтипизирован.
Подсказка
Методы tp_as_number используют общий подход для вызова любой функции, которая была зарегистрирована для обработки операции. При импорте _multiarray_umath module, он задаёт числовые операции для всех массивов соответствующим ufunc. Этот выбор может быть изменён с помощью PyUFunc_ReplaceLoopBySignature. Методы tp_str и tp_repr также могут быть изменены с помощью PyArray_SetStringFunction.
PyUFunc_Type и PyUFuncObject
-
PyUFunc_Type -
Объект ufunc реализуется созданием
PyUFunc_Type. Это очень простой тип, который реализует только базовые поведение getattribute, вывода и имеет поведение вызова, позволяющее этим объектам действовать как функции. Основная идея ufunc заключается в хранении ссылки на быстрые одномерные (векторные) циклы для каждого типа данных, поддерживающего операцию. Эти одномерные циклы имеют одинаковую сигнатуру и являются ключом к созданию нового ufunc. Они вызываются общим кодом циклов, как требуется для реализации N-мерной функции. Также определены некоторые общие одномерные циклы для плавающих и комплексных плавающих массивов, позволяющие определить ufunc с использованием одной скалярной функции (например atanh).
-
PyUFuncObject -
Ядро ufunc — это
PyUFuncObject, которое содержит всю необходимую информацию для вызова подлежащих C-кодовых циклов, выполняющих фактическую работу. Хотя оно описано здесь для полноты, его следует рассматривать как внутреннюю часть NumPy и манипулировать им с помощьюPyUFunc_*функций. Размер этой структуры может меняться в различных версиях NumPy. Чтобы обеспечить совместимость:- Никогда не объявляйте не указатель экземпляр структуры.
- Никогда не выполняйте арифметические операции над указателями.
- Никогда не используйте
sizeof(PyUFuncObject)
Его структура следующая:
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; int core_enabled; int core_num_dim_ix; int *core_num_dims; int *core_dim_ixs; int *core_offsets; char *core_signature; PyUFunc_TypeResolutionFunc *type_resolver; PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector; PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector; npy_uint32 *op_flags; npy_uint32 *iter_flags; /* new in API version 0x0000000D */ npy_intp *core_dim_sizes; npy_intp *core_dim_flags; } PyUFuncObject;-
int PyUFuncObject.nin -
Количество входных аргументов.
-
int PyUFuncObject.nout -
Количество выходных аргументов.
-
int PyUFuncObject.nargs -
Общее количество аргументов (nin + nout). Это значение должно быть меньше
NPY_MAXARGS.
-
int PyUFuncObject.identity -
Либо
PyUFunc_One, либоPyUFunc_Zero, либоPyUFunc_NoneилиPyUFunc_AllOnesдля указания тождества для данной операции. Оно используется только для вызова 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-мерных циклов (встроенных типов данных) доступно.
-
int PyUFuncObject.reserved1 -
Не используется.
-
char *PyUFuncObject.name -
Строковое имя ufunc. Оно используется динамически для построения атрибута __doc__ ufunc.
-
char *PyUFuncObject.types -
Массив из
8-битных номеров типов, содержащих сигнатуру типа для функции для каждого из поддерживаемых (встроенных) типов данных. Для каждой из ntypes функций соответствующий набор номеров типов в этом массиве показывает, как должен интерпретироваться аргумент args в 1-мерном цикле по векторам. Эти номера типов не обязательно должны быть одинаковыми, и поддерживаются ufunc с различными типами.
-
char *PyUFuncObject.doc -
Документация для ufunc. Она не должна содержать сигнатуру функции, так как она генерируется динамически при получении атрибута __doc__.
-
void *PyUFuncObject.ptr -
Любая динамически выделенная память. В настоящее время она используется для динамических ufunc, созданных из функции Python, для хранения места для членов types, data и name.
-
PyObject *PyUFuncObject.obj -
Для ufunc, динамически созданных из функций Python, этот член содержит ссылку на подлежащую функцию Python.
-
PyObject *PyUFuncObject.userloops -
Словарь пользовательских 1-мерных циклов по векторам (хранящихся как указатели CObject) для пользовательских типов. Пользователь может зарегистрировать цикл для любого пользовательского типа. Он извлекается по номеру типа. Номера пользовательских типов всегда больше
NPY_USERDEF.
-
int PyUFuncObject.core_enabled -
0 для скалярных ufunc; 1 для обобщенных ufunc
-
int PyUFuncObject.core_num_dim_ix -
Количество различных имён измерений ядра в сигнатуре.
-
int *PyUFuncObject.core_num_dims -
Количество измерений ядра каждого аргумента.
-
int *PyUFuncObject.core_dim_ixs -
Индексы измерений в уплощенной форме; индексы аргумента
kхранятся вcore_dim_ixs[core_offsets[k] : core_offsets[k] + core_numdims[k]]
-
int *PyUFuncObject.core_offsets -
Позиция первого измерения ядра каждого аргумента в
core_dim_ixs, эквивалентно cumsum(core_num_dims)
-
char *PyUFuncObject.core_signature -
Строка ядра сигнатуры.
-
PyUFunc_TypeResolutionFunc *PyUFuncObject.type_resolver -
Функция, которая разрешает типы и заполняет массив типами данных для входных и выходных значений.
-
PyUFunc_LegacyInnerLoopSelectionFunc *PyUFuncObject.legacy_inner_loop_selector -
Функция, которая возвращает внутренний цикл. Приставка «legacy» возникает потому, что для NumPy 1.6 планировалась лучшая версия. Но эта версия пока не реализована.
-
void *PyUFuncObject.reserved2 -
Для возможного будущего выбора цикла с другой сигнатурой.
-
PyUFunc_MaskedInnerLoopSelectionFunc *PyUFuncObject.masked_inner_loop_selector -
Функция, которая возвращает внутренний цикл для ufunc с масками.
-
npy_uint32 PyUFuncObject.op_flags -
Переопределяет флаги операндов по умолчанию для каждого операнда ufunc.
-
npy_uint32 PyUFuncObject.iter_flags -
Переопределяет флаги nditer по умолчанию для ufunc.
Добавлен в API версии 0x0000000D
-
npy_intp *PyUFuncObject.core_dim_sizes -
Для каждого уникального измерения ядра возможный замороженный размер, если
UFUNC_CORE_DIM_SIZE_INFERREDравно 0.
-
npy_uint32 *PyUFuncObject.core_dim_flags -
Для каждого уникального измерения ядра набор
UFUNC_CORE_DIM*флагов-
UFUNC_CORE_DIM_CAN_IGNOREесли имя измерения оканчивается на? -
UFUNC_CORE_DIM_SIZE_INFERREDесли размер измерения будет определяться из операндов, а не из замороженной сигнатуры.
-
PyArrayIter_Type и PyArrayIterObject
-
PyArrayIter_Type -
Это объект итератора, который упрощает циклирование по N-мерному массиву. Он возвращается атрибутом flat ndarray. Он также широко используется во внутренней реализации для циклирования по N-мерному массиву. Интерфейс tp_as_mapping реализован таким образом, чтобы объект итератора можно было индексировать (с помощью 1-мерного индексирования), и несколько методов реализованы через таблицу tp_methods. Этот объект реализует метод next и может использоваться везде, где в Python используется итератор.
-
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 -
где
— количество измерений в базовом массиве.
-
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 -
Флаг, истинный, если базовый массив
NPY_ARRAY_C_CONTIGUOUS. Используется для упрощения вычислений, когда это возможно.
-
Более подробное описание использования итератора массива на уровне C приведено в последующих разделах. Как правило, вам не нужно беспокоиться о внутренней структуре объекта-итератора, а только взаимодействовать с ним с помощью макросов PyArray_ITER_NEXT (it), PyArray_ITER_GOTO (it, dest) или PyArray_ITER_GOTO1D (it, index). Все эти макросы требуют в качестве аргумента it объект PyArrayIterObject *.
PyArrayMultiIter_Type и PyArrayMultiIterObject
-
PyArrayMultiIter_Type -
Этот тип предоставляет итератор, который обобщает концепцию вещания. Он позволяет
массивам вещаться вместе, так что цикл прогрессирует в стиле C, непрерывно над вещаемым массивом. Соответствующей структурой C является
PyArrayMultiIterObject, макет памяти которой должен начинаться с любого объекта obj, переданного в функциюPyArray_Broadcast(obj). Вещание выполняется путём настройки итераторов массивов так, что каждый итератор представляет вещаемую форму и размер, но его шаги настраиваются так, что на каждой итерации используется правильный элемент массива.
-
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
-
PyArrayNeighborhoodIter_Type -
Объект-итератор, который упрощает циклы по N-мерному окружению.
-
PyArrayNeighborhoodIterObject -
Структура C, соответствующая объекту типа
PyArrayNeighborhoodIter_Type, — этоPyArrayNeighborhoodIterObject.typedef struct { PyObject_HEAD int nd_m1; npy_intp index, 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; npy_bool contiguous; npy_intp bounds[NPY_MAXDIMS][2]; npy_intp limits[NPY_MAXDIMS][2]; npy_intp limits_sizes[NPY_MAXDIMS]; npy_iter_get_dataptr_t translate; npy_intp nd; npy_intp dimensions[NPY_MAXDIMS]; PyArrayIterObject* _internal_iter; char* constant; int mode; } PyArrayNeighborhoodIterObject;
PyArrayFlags_Type и PyArrayFlagsObject
-
PyArrayFlags_Type -
При получении атрибута flags из Python, создаётся специальный встроенный объект этого типа. Этот специальный тип упрощает работу с различными флагами путём доступа к ним как к атрибутам или путём доступа к ним как к словарю, где имена флагов являются ключами.
-
PyArrayFlagsObject -
typedef struct PyArrayFlagsObject { PyObject_HEAD PyObject *arr; int flags; } PyArrayFlagsObject;
Типы скалярных массивов
Для каждого из встроенных типов данных, которые могут присутствовать в массиве, существует тип Python. Большинство из них являются простыми оболочками над соответствующим типом данных в C. Имена типов в C — это Py{TYPE}ArrType_Type , где {TYPE} может быть
Эти имена типов являются частью 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__был извлечён) и укажите член base нового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-структур, содержащих информацию, необходимую для определения одномерного цикла для ufunc для каждой определенной сигнатуры пользовательского типа данных.
-
PyArrayMapIter_Type -
Обработка продвинутого индексирования осуществляется с помощью этого типа Python. Это просто слабая оболочка вокруг C-структуры, содержащей переменные, необходимые для индексирования массивов с помощью расширенных индексов. Связанная C-структура,
PyArrayMapIterObject, полезна, если вы пытаетесь понять код сопоставления индексов с расширенными индексами. Она определена в заголовкеarrayobject.h. Этот тип не представлен в Python и может быть заменён C-структурой. Как тип Python он использует управляемое памятью с подсчётом ссылок.
© 2005–2019 NumPy Developers
Licensed under the 3-clause BSD License.
https://docs.scipy.org/doc/numpy-1.17.0/reference/c-api.types-and-structures.html