Типы 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 — это тип описателя типа данных, экземпляры которого описывают данные. Наконец, существует 21 новый скалярный тип массива, представляющий собой новые скаляры Python, соответствующие каждому из основных типов данных, доступных для массивов. Ещё 10 типов являются плейсхолдерами, которые позволяют скалярам массивов вписываться в иерархию фактических типов Python.
PyArray_Type
-
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;
-
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, связанный с этим массивом. Существует два случая использования: 1) Если этот массив не владеет своей памятью, то base указывает на объект Python, который им владеет (возможно, другой объект массива), 2) Если для этого массива установлен флаг (устаревший)
NPY_ARRAY_UPDATEIFCOPYили :c:data: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
-
PyArrayDescr_Type -
PyArrayDescr_Type— это встроенный тип объектов описателей типа данных, используемых для описания того, как интерпретировать байты, составляющие массив. Существует 21 статически определённый объектPyArray_Descrдля встроенных типов данных. Хотя они участвуют в подсчёте ссылок, их счётчик ссылок никогда не должен достигать нуля. Также поддерживается динамическая таблица пользовательских объектовPyArray_Descr. После «регистрации» объекта описателя типа данных он также не должен быть удалён. ФункцияPyArray_DescrFromType(…) может использоваться для извлечения объектаPyArray_Descrпо номеру перечисления типа (встроенному или пользовательскому).
-
PyArray_Descr -
Структура
PyArray_Descrявляется основой дляPyArrayDescr_Type. Хотя она описана здесь для полноты, её следует считать внутренней для NumPy и манипулировать ею посредством функций и макросовPyArrayDescr_*илиPyDataType*. Размер этой структуры может меняться в разных версиях NumPy. Для обеспечения совместимости:- Никогда не объявляйте не-указательную (non-pointer) экземпляра структуры
- Никогда не выполняйте арифметику указателей
- Никогда не используйте
sizof(PyArray_Descr)
Она имеет следующую структуру:
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-битные/символьные строки Unicode, а ‘V’ — произвольные.
-
char PyArray_Descr.type -
Традиционный символьный код, указывающий тип данных.
-
char PyArray_Descr.byteorder -
Символ, указывающий порядок байтов: ‘>’ (big-endian), ‘<’ (little- endian), ‘=’ (родной), ‘|’ (несущественный, игнорировать). Все встроенные типы данных имеют порядок байтов ‘=’.
-
int PyArray_Descr.flags -
Флаг бита типа данных, определяющий, демонстрирует ли тип данных поведение, подобное массиву объектов. Каждый бит в этом члене — это флаг, которые имеют следующие названия:
-
NPY_ITEM_REFCOUNT
-
NPY_ITEM_HASOBJECT -
Указывает, что элементы этого типа данных должны иметь счётчик ссылок (используя
Py_INCREFиPy_DECREF).
-
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-style contiguous другого описателя типа данных. Другими словами, каждый элемент, который описывает этот описатель, на самом деле является массивом некоторого другого базового описателя. Это наиболее полезно в качестве описателя типа данных для поля в другом описателе типа данных. Поле 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-style contiguous) подмассива в виде кортежа 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)со значением NULL для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) -
Указатель на функцию, которая возвращает ИСТИНА, если элемент
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или 0-мерный массив, содержащий данные (если это необходимо для определения типа скаляра). Возвращаемое значение должно иметь тип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, включая интерфейсы 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
-
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используется, если extra_data не требуется. Несколько вызовов 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-мерном векторном цикле. Эти номера типов не обязательно должны быть одинаковыми, и поддерживаются ufuncs смешанных типов.
-
char *PyUFuncObject.doc -
Документация для ufunc. Не должна содержать сигнатуру функции, так как она генерируется динамически при получении __doc__.
-
void *PyUFuncObject.ptr -
Любая динамически выделенная память. В настоящее время используется для динамически созданных ufunc из Python-функции для хранения места для членов types, data и name.
-
PyObject *PyUFuncObject.obj -
Для ufuncs, динамически созданных из 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 -
Функция, которая разрешает типы и заполняет массив dtypes для входных и выходных данных
-
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
-
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 -
Индекс в массиве с
измерениями.
-
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
-
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
-
PyArrayNeighborhoodIter_Type -
Это объект-итератор, который упрощает перебор N-мерного окрестного массива.
-
PyArrayNeighborhoodIterObject -
Структура C, соответствующая объекту
PyArrayNeighborhoodIter_Type, — этоPyArrayNeighborhoodIterObject.
PyArrayFlags_Type
-
PyArrayFlags_Type -
При получении атрибута flags из Python создаётся специальный встроенный объект этого типа. Этот специальный тип облегчает работу с различными флагами, позволяя обращаться к ним как к атрибутам или как к элементам словаря, где ключами являются имена флагов.
ScalarArrayTypes
Для каждого из различных встроенных типов данных, которые могут присутствовать в массиве, существует тип 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-like 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.16.1/reference/c-api.types-and-structures.html