Spec-Zone.ru › NumPy 1.13

Стандартные подклассы массивов

Класс ndarray в NumPy является «классом нового стиля» встроенного типа Python. Поэтому к нему можно наследовать (в Python или C), если это необходимо. Поэтому он может служить основой для многих полезных классов. Часто выбор между наследованием объекта массива или использованием ядра массива как внутренней части нового класса является сложным решением и может быть просто вопросом выбора. NumPy предоставляет несколько инструментов для упрощения взаимодействия вашего нового объекта с другими объектами массивов, и поэтому окончательный выбор может не иметь большого значения. Один из способов упростить вопрос — спросить себя, можно ли заменить интересуемый объект одним массивом или же он действительно требует двух или более массивов в своей основе.

Обратите внимание, что asarray всегда возвращает базовый класс ndarray. Если вы уверены, что ваше использование объекта массива может обрабатывать любой подкласс ndarray, то asanyarray может использоваться для более чистого распространения подклассов через вашу подпрограмму. В принципе, подкласс может переопределить любой аспект массива, и поэтому, при строгих правилах, asanyarray будет редко полезным. Однако большинство подклассов объекта массива не будут переопределять определённые аспекты объекта массива, такие как интерфейс буфера или атрибуты массива. Важный пример того, почему ваша подпрограмма может не обработать произвольный подкласс массива, состоит в том, что матрицы переопределяют оператор «*» на матричное умножение, а не на поэлементное умножение.

Специальные атрибуты и методы

См. также

Наследование ndarray

NumPy предоставляет несколько «крючков», которые классы могут настроить:

class.__array_ufunc__(ufunc, method, *inputs, **kwargs)

Добавлена в версии 1.13.

Примечание

API является предварительным, т.е. мы пока не гарантируем обратную совместимость.

Любой класс, являющийся или не являющийся подклассом ndarray, может определить этот метод или установить его в None, чтобы переопределить поведение ufunc NumPy. Это работает очень похоже на Python’s __mul__ и другие бинарные операторные процедуры.

  • ufunc — это объект ufunc, который был вызван.
  • method — строка, указывающая, какой метод Ufunc был вызван (один из "__call__", "reduce", "reduceat", "accumulate", "outer", "inner").
  • inputs — кортеж входных аргументов для ufunc.
  • kwargs — словарь, содержащий необязательные входные аргументы ufunc. Если указаны, любые out аргументы, как позиционные, так и ключевые, передаются как tuple в kwargs. Подробности см. в разделе Универсальные функции (ufunc).

Метод должен вернуть либо результат операции, либо NotImplemented, если запрашиваемая операция не реализована.

Если у одного из входных или выходных аргументов есть метод __array_ufunc__, он выполняется вместо ufunc. Если более одного аргумента реализуют метод __array_ufunc__, они выполняются в порядке: подклассы перед суперклассами, входные аргументы перед выходными, в противном случае слева направо. Первая процедура, возвращающая значение, отличное от NotImplemented, определяет результат. Если все операции __array_ufunc__ возвращают NotImplemented, возникает TypeError.

Примечание

Мы намерены повторно реализовать функции numpy в виде (обобщенных) Ufunc, в этом случае их можно будет переопределить методом __array_ufunc__. Хороший кандидат — matmul, который в настоящее время не является Ufunc, но его можно относительно легко переписать в виде (набора) обобщенных Ufunc. То же самое может произойти с функциями, такими как median, min, и argsort.

Как и в случае с некоторыми другими специальными методами в Python, такими как __hash__ и __iter__, можно указать, что ваш класс не поддерживает ufunc, установив __array_ufunc__ = None. Ufunc всегда вызывают TypeError при вызове на объекте, который устанавливает __array_ufunc__ = None.

Наличие __array_ufunc__ также влияет на то, как ndarray обрабатывает бинарные операции, такие как arr + obj и arr < obj, когда arr является ndarray, а obj — экземпляром пользовательского класса. Есть два варианта. Если obj.__array_ufunc__ существует и не равно None, то ndarray.__add__ и аналогичные им делегируют механизму ufunc, что означает, что arr + obj становится np.add(arr, obj), а затем add вызывает obj.__array_ufunc__. Это полезно, если вы хотите определить объект, который ведет себя как массив.

В противном случае, если obj.__array_ufunc__ установлено в None, то в качестве специального случая специальные методы, такие как ndarray.__add__, будут замечать это и безоговорочно вызывать TypeError. Это полезно, если вы хотите создавать объекты, которые взаимодействуют с массивами через бинарные операции, но сами по себе не являются массивами. Например, система обработки единиц может иметь объект m, представляющий единицу «метр», и захотеть поддержать синтаксис arr * m для обозначения того, что массив имеет единицы «метр», но не хочет иначе взаимодействовать с массивами через ufunc или иным образом. Это можно сделать, установив __array_ufunc__ = None и определив методы __mul__ и __rmul__. (Обратите внимание, что это означает, что написание __array_ufunc__ который всегда возвращает NotImplemented не совсем то же самое, что установка __array_ufunc__ = None: в первом случае arr + obj будет поднимать TypeError, а во втором случае можно определить метод __radd__ для предотвращения этого.)

Вышесказанное не относится к операторам in-place, для которых ndarray никогда не возвращает NotImplemented. Следовательно, arr += obj всегда приведет к TypeError. Это происходит потому, что для массивов операции in-place не могут быть универсально заменены простой обратной операцией. (Например, по умолчанию arr += obj будет переведено в arr = arr + obj, т.е. arr будет заменено, что не соответствует ожидаемому для операций in-place с массивами.)

Примечание

Если вы определили __array_ufunc__:

  • Если вы не являетесь подклассом ndarray, мы рекомендуем вашему классу определить специальные методы, такие как __add__ и __lt__, которые делегируют ufunc так же, как это делает ndarray. Легкий способ сделать это — унаследовать от NDArrayOperatorsMixin.
  • Если вы наследуете от ndarray, мы рекомендуем разместить всю вашу логику переопределения в __array_ufunc__ и не переопределять специальные методы. Это гарантирует, что иерархия классов определяется только в одном месте, а не раздельно механизмом ufunc и правилами бинарных операций (что отдает предпочтение специальным методам подклассов; альтернативный способ обеспечить единственное место определения иерархии, установкой __array_ufunc__ в None, кажется очень неожиданным и поэтому запутанным, так как тогда подкласс вообще не будет работать с ufunc).
  • ndarray определяет свой собственный __array_ufunc__, который вычисляет ufunc, если у аргументов нет переопределений, и возвращает NotImplemented в противном случае. Это может быть полезно для подклассов, для которых __array_ufunc__ преобразует любые экземпляры своего собственного класса в ndarray: он затем может передать их своему суперклассу с помощью super().__array_ufunc__(*inputs, **kwargs), и, наконец, вернуть результаты после возможного обратного преобразования. Преимущество этой практики заключается в том, что она гарантирует возможность создания иерархии подклассов, которые расширяют поведение. Подробнее см. Наследование от ndarray.
END_OF_DOCUMENT_MARKER

Примечание

Если класс определяет метод __array_ufunc__, это отключает механизм __array_wrap__, __array_prepare__, __array_priority__, описанный ниже для ufunc (который может быть в конечном итоге устаревшим).

class.__array_finalize__(obj)

Этот метод вызывается всякий раз, когда система внутренне выделяет новый массив из obj, где obj является подклассом (подтипом) ndarray. Его можно использовать для изменения атрибутов self после построения (например, для обеспечения 2-мерной матрицы) или для обновления метаданных из «родителя». Подклассы наследуют по умолчанию реализацию этого метода, которая ничего не делает.

class.__array_prepare__(array, context=None)

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

Примечание

Для ufuncs ожидается, что этот метод в конечном итоге будет устаревшим в пользу __array_ufunc__.

class.__array_wrap__(array, context=None)

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

Примечание

Для ufuncs ожидается, что этот метод в конечном итоге будет устаревшим в пользу __array_ufunc__.

class.__array_priority__

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

Примечание

Для ufuncs ожидается, что этот метод в конечном итоге будет устаревшим в пользу __array_ufunc__.

class.__array__([dtype])

Если класс (подкласс ndarray или нет), имеющий метод __array__, используется как выходной объект ufunc, результаты будут записаны в объект, возвращённый методом __array__. Аналогичное преобразование выполняется для входных массивов.

Объекты матриц

matrix объекты наследуют от ndarray и, следовательно, имеют те же атрибуты и методы, что и ndarray. Однако есть шесть важных различий между объектами матриц, которые могут привести к неожиданным результатам, когда вы используете матрицы, но ожидаете, что они будут действовать как массивы:

  1. Объекты матриц могут быть созданы с использованием строковой записи, что позволяет использовать синтаксис в стиле Matlab, где пробелы отделяют столбцы, а точки с запятой (';') отделяют строки.
  2. Объекты матриц всегда двухмерные. Это имеет далеко идущие последствия, так как m.ravel() по-прежнему двухмерный (с 1 в первом измерении), а выбор элементов возвращает двухмерные объекты, так что поведение последовательности принципиально отличается от массивов.
  3. Объекты матриц перезаписывают умножение, чтобы оно выполнялось как матричное умножение. Убедитесь, что вы понимаете это для функций, которые могут получать матрицы. Особенно с учётом того, что asanyarray(m) возвращает матрицу, когда m является матрицей.
  4. Объекты матриц перезаписывают возведение в степень, чтобы оно выполнялось как возведение матрицы в степень. То же предупреждение о применении возведения в степень внутри функции, использующей asanyarray(...), для получения объекта массива справедливо и для этого факта.
  5. Значение __array_priority__ по умолчанию для объектов матриц составляет 10.0, и поэтому смешанные операции с ndarray всегда приводят к матрицам.
  6. Матрицы имеют специальные атрибуты, которые упрощают вычисления. Это

    matrix.T Возвращает транспонированную матрицу.
    matrix.H Возвращает (комплексно) сопряжённую транспонированную self.
    matrix.I Возвращает (мультипликативную) обратную матрицу обратимой self.
    matrix.A Возвращает self как объект ndarray.

Предупреждение

Объекты матриц перезаписывают умножение, «*», и возведение в степень, «**», чтобы они выполнялись как матричное умножение и возведение матрицы в степень соответственно. Если ваша подпрограмма может принимать подклассы, и вы не преобразуете их в массивы базового класса, то вы должны использовать ufuncs multiply и power, чтобы быть уверенными, что вы выполняете правильную операцию для всех входных данных.

Класс матриц является подклассом ndarray в Python и может использоваться в качестве справочника по тому, как создать собственный подкласс ndarray. Матрицы могут быть созданы из других матриц, строк и всего, что может быть преобразовано в ndarray . Название «mat» является псевдонимом для «matrix» в NumPy.

matrix Возвращает матрицу из объекта типа array-like или из строки данных.
asmatrix(data[, dtype]) Рассматривает входные данные как матрицу.
bmat(obj[, ldict, gdict]) Создаёт объект матрицы из строки, вложенной последовательности или массива.

Пример 1: Создание матрицы из строки

>>> a=mat('1 2 3; 4 5 3')
>>> print (a*a.T).I
[[ 0.2924 -0.1345]
 [-0.1345  0.0819]]

Пример 2: Создание матрицы из вложенной последовательности

>>> mat([[1,5,10],[1.0,3,4j]])
matrix([[  1.+0.j,   5.+0.j,  10.+0.j],
        [  1.+0.j,   3.+0.j,   0.+4.j]])

Пример 3: Создание матрицы из массива

>>> mat(random.rand(3,3)).T
matrix([[ 0.7699,  0.7922,  0.3294],
        [ 0.2792,  0.0101,  0.9219],
        [ 0.3398,  0.7571,  0.8197]])

Массивы с отображением памяти на файл

Массивы с отображением памяти на файлы полезны для чтения и/или изменения небольших фрагментов большого файла с регулярной структурой без чтения всего файла в память. Простой подкласс ndarray использует файл с отображением памяти для буфера данных массива. Для небольших файлов накладные расходы на чтение всего файла в память обычно не существенны, однако для больших файлов использование отображения памяти может сэкономить значительные ресурсы.

Массивы с отображением памяти на файлы имеют один дополнительный метод (помимо наследуемых от ndarray): .flush(), который пользователь должен вызывать вручную, чтобы гарантировать, что любые изменения в массиве действительно записываются на диск.

memmap Создать отображение памяти на массив, хранящийся в бинарном файле на диске.
memmap.flush() Записать любые изменения в массиве в файл на диске.

Пример:

>>> a = memmap('newfile.dat', dtype=float, mode='w+', shape=1000)
>>> a[10] = 10.0
>>> a[30] = 30.0
>>> del a
>>> b = fromfile('newfile.dat', dtype=float)
>>> print b[10], b[30]
10.0 30.0
>>> a = memmap('newfile.dat', dtype=float)
>>> print a[10], a[30]
10.0 30.0

Символьные массивы (numpy.char)

См. также

Создание символьных массивов (numpy.char)

Примечание

Класс chararray существует для обратной совместимости с Numarray, его не рекомендуется использовать для новых разработок. Начиная с numpy 1.4, если вам нужны массивы строк, рекомендуется использовать массивы типа dtype object_, string_ или unicode_, и использовать свободные функции в модуле numpy.char для быстрых векторизованных строковых операций.

Это расширенные массивы типа string_ или типа unicode_. Эти массивы наследуют от ndarray, но специально определяют операции +, *, и % по элементам (с учётом трансляции) на основе поэлементного сравнения. Эти операции недоступны для стандартного ndarray типа символов. Кроме того, chararray имеет все стандартные string (и unicode) методы, выполняющие их по элементам. Возможно, самый простой способ создать chararray — использовать self.view(chararray), где self — ndarray со строковым или юникодовым типом данных. Однако chararray также можно создать с помощью конструктора numpy.chararray или функции numpy.char.array:

chararray Предоставляет удобный вид на массивы строковых и юникодовых значений.
core.defchararray.array(obj[, itemsize, ...]) Создаёт chararray.

Другое отличие от стандартного ndarray типа данных str заключается в том, что chararray наследует функцию, введённую в Numarray, которая игнорирует пробелы в конце любого элемента массива при получении элементов и выполнении операций сравнения.

Массивы записей (numpy.rec)

См. также

Создание массивов записей (numpy.rec), Функции работы с типами данных, Объекты типов данных (dtype).

NumPy предоставляет класс recarray, который позволяет обращаться к полям структурированного массива как к атрибутам, и соответствующий скалярный объект типа данных record.

recarray Создаёт ndarray, позволяющий обращаться к полям с помощью атрибутов.
record Скалярный тип данных, позволяющий обращаться к полям как к атрибутам.

Маскированные массивы (numpy.ma)

См. также

Маскированные массивы

Стандартный контейнерный класс

Для обеспечения обратной совместимости и в качестве стандартного «контейнерного» класса, класс UserArray из Numeric был перенесён в NumPy и переименован в numpy.lib.user_array.container. Контейнерный класс — это класс Python, атрибут self.array которого является ndarray. Наследование с множественным наследованием, вероятно, проще с помощью numpy.lib.user_array.container, чем с самим ndarray, поэтому он включён по умолчанию. Здесь он не документируется подробно, помимо упоминания его существования, поскольку рекомендуется использовать класс ndarray напрямую, если это возможно.

numpy.lib.user_array.container(data[, ...]) Стандартный контейнерный класс для простого множественного наследования.

Итераторы массивов

Итераторы — мощная концепция для обработки массивов. По сути, итераторы реализуют обобщённый цикл for. Если myiter — объект итератора, то код Python:

for val in myiter:
    ...
    some code involving val
    ...

вызывает val = myiter.next() многократно, пока не будет вызвано StopIteration итератором. Существует несколько способов итерирования по массиву, которые могут быть полезны: стандартное итерирование, итерирование по плоскому массиву и N-мерное перечисление.

Стандартное итерирование

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

for i in range(arr.shape[0]):
    val = arr[i]

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

>>> a = arange(24).reshape(3,2,4)+10
>>> for val in a:
...     print 'item:', val
item: [[10 11 12 13]
 [14 15 16 17]]
item: [[18 19 20 21]
 [22 23 24 25]]
item: [[26 27 28 29]
 [30 31 32 33]]

Итерирование по плоскому массиву

ndarray.flat Итератор по 1-мерному массиву.

Как уже упоминалось, атрибут flat объектов ndarray возвращает итератор, который будет перебирать весь массив в стиле C, в непрерывном порядке.

>>> for i, val in enumerate(a.flat):
...     if i%5 == 0: print i, val
0 10
5 15
10 20
15 25
20 30

Здесь я использовал встроенный итератор enumerate для возврата индекса итератора, а также значения.

N-мерное перечисление

ndenumerate(arr) Итератор индексов многомерного массива.

Иногда может быть полезно получить N-мерный индекс во время итерации. Итератор ndenumerate может этого достичь.

>>> for i, val in ndenumerate(a):
...     if sum(i)%5 == 0: print i, val
(0, 0, 0) 10
(1, 1, 3) 25
(2, 0, 3) 29
(2, 1, 2) 32

Итератор для трансляции

broadcast Создаёт объект, имитирующий трансляцию.

Общая концепция трансляции также доступна из Python с помощью итератора broadcast. Этот объект принимает N объекты в качестве входных данных и возвращает итератор, который возвращает кортежи, содержащие каждый элемент входной последовательности в широковещательном результате.

>>> for val in broadcast([[1,0],[2,3]],[0,1]):
...     print val
(1, 0)
(0, 1)
(2, 0)
(3, 1)

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

Spec-Zone.ru

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