Стандартные подклассы массивов
В NumPy ndarray — это встроенный тип Python «нового стиля». Поэтому от него можно наследовать (в Python или C), если это необходимо. Поэтому он может служить основой для многих полезных классов. Часто выбор между наследованием от объекта массива или использованием ядра массива как внутренней части нового класса является непростым решением и может быть просто делом выбора. NumPy предоставляет несколько инструментов для упрощения взаимодействия вашего нового объекта с другими объектами массивов, и поэтому выбор в итоге может не иметь большого значения. Один из способов упростить вопрос — спросить себя, можно ли заменить интересующий вас объект одним массивом или он действительно требует двух или более массивов в своей основе.
Обратите внимание, что asarray всегда возвращает базовый класс ndarray. Если вы уверены, что ваше использование объекта массива может обрабатывать любой подкласс ndarray, то asanyarray можно использовать для более чистого распространения подклассов через вашу подпрограмму. В принципе, подкласс мог бы переопределить любой аспект массива, и поэтому при строгих ограничениях asanyarray редко будет полезен. Однако большинство подклассов объекта массива не переопределяют определённые аспекты объекта массива, такие как интерфейс буфера или атрибуты массива. Однако одним важным примером того, почему ваша подпрограмма может не справиться с произвольным подклассом массива, является то, что матрицы переопределяют оператор «*» для матричного умножения вместо поэлементного умножения.
Специальные атрибуты и методы
См. также
Numpy предоставляет несколько «зацепок», которые классы могут настроить:
-
class.__numpy_ufunc__(self, ufunc, method, i, inputs, **kwargs) -
Введено в версии 1.10.
Любой класс (подкласс ndarray или нет) может определить этот метод для переопределения поведения функций Numpy. Это работает очень похоже на Python
__mul__и другие функции бинарных операций.- ufunc — это объект ufunc, который был вызван.
-
method — строка, указывающая, какой метод Ufunc был вызван (один из
"__call__","reduce","reduceat","accumulate","outer","inner"). - i — индекс self в inputs.
-
inputs — кортеж входных аргументов для
ufunc -
kwargs — словарь, содержащий необязательные входные аргументы ufunc. Аргумент
outвсегда содержится в kwargs, если задан. Подробности см. в разделе Универсальные функции (ufunc).
Метод должен вернуть либо результат операции, либо
NotImplemented, если запрошенная операция не реализована.Если один из аргументов имеет метод
__numpy_ufunc__, он выполняется вместо функции ufunc. Если более одного входного аргумента реализуют__numpy_ufunc__, они пытаются в порядке: подклассы перед суперклассами, в противном случае слева направо. Первая процедура, возвращающая что-то отличное отNotImplemented, определяет результат. Если все__numpy_ufunc__операции возвращаютNotImplemented, возникаетTypeError.Если подкласс
ndarrayопределяет метод__numpy_ufunc__, это отключает механизм__array_wrap__,__array_prepare__,__array_priority__ниже.Примечание
Помимо функций ufunc,
__numpy_ufunc__также переопределяет поведениеnumpy.dot, хотя это и не функция ufunc.Примечание
Если вы также определите методы переопределения бинарных операторов справа (например,
__rmul__) или операций сравнения (например,__gt__) в вашем классе, они имеют приоритет над механизмом__numpy_ufunc__при разрешении результатов бинарных операций (например,ndarray_obj * your_obj).Технический частный случай:
ndarray.__mul__возвращаетNotImplementedесли другой объект не является подклассомndarrayи определяет как__numpy_ufunc__, так и__rmul__. Аналогичное исключение применяется к другим операциям, кроме умножения.В таком случае, при вычислении бинарной операции, такой как
ndarray_obj * your_obj, ваш метод__numpy_ufunc__не будет вызван. Вместо этого выполнение передаётся вашему правой части__rmul__операции, согласно стандартным правилам Python для переопределения операторов.Аналогичный частный случай относится к операциям на месте: если вы определите
__rmul__, тоndarray_obj *= your_objне будет вызывать вашу реализацию__numpy_ufunc__. Вместо этого происходит стандартное поведение Pythonndarray_obj = ndarray_obj * your_obj.Обратите внимание, что вышеупомянутое обсуждение относится только к встроенному механизму бинарных операций Python.
np.multiply(ndarray_obj, your_obj)всегда вызывает только ваш__numpy_ufunc__, как и ожидалось.
-
class.__array_finalize__(self) -
Этот метод вызывается всякий раз, когда система внутренне выделяет новый массив из obj, где obj — подкласс (подтип)
ndarray. Его можно использовать для изменения атрибутов self после построения (например, для обеспечения двумерной матрицы) или для обновления метаданных из «родителя». Подклассы унаследуют по умолчанию реализацию этого метода, которая ничего не делает.
-
class.__array_prepare__(array, context=None) -
В начале каждой функции ufunc этот метод вызывается на объекте входа с самым высоким приоритетом массива или на выходном объекте, если он был задан. Выходной массив передается, и то, что возвращается, передается в ufunc. Подклассы наследуют по умолчанию реализацию этого метода, которая просто возвращает выходной массив без изменений. Подклассы могут использовать этот метод для преобразования выходного массива в экземпляр подкласса и обновления метаданных перед возвращением массива функции ufunc для вычисления.
-
class.__array_wrap__(array, context=None) -
В конце каждой функции ufunc этот метод вызывается на объекте входа с самым высоким приоритетом массива или на выходном объекте, если он был задан. Массив, вычисленный функцией ufunc, передается, и то, что возвращается, передается пользователю. Подклассы наследуют по умолчанию реализацию этого метода, которая преобразует массив в новый экземпляр класса объекта. Подклассы могут использовать этот метод для преобразования выходного массива в экземпляр подкласса и обновления метаданных перед возвращением массива пользователю.
-
class.__array_priority__ -
Значение этого атрибута используется для определения типа объекта, который нужно вернуть в ситуациях, когда существует более одной возможности для типа Python возвращаемого объекта. Подклассы наследуют значение по умолчанию 0.0 для этого атрибута.
-
class.__array__([dtype]) -
Если класс (подкласс ndarray или нет), имеющий метод
__array__, используется как выходной объект функции ufunc, результаты будут записаны в объект, возвращаемый__array__. Аналогичное преобразование выполняется с входными массивами.
Объекты матриц
matrix объекты наследуют от ndarray и поэтому имеют те же атрибуты и методы, что и ndarray. Однако существует шесть важных различий между объектами матриц, которые могут привести к неожиданным результатам, когда вы используете матрицы, но ожидаете, что они будут вести себя как массивы:
- Объекты матриц могут создаваться с использованием строковой нотации, позволяющей использовать синтаксис в стиле Matlab, где пробелы отделяют столбцы, а точки с запятой (';') отделяют строки.
- Объекты матриц всегда двумерны. Это имеет далеко идущие последствия, так как m.ravel() по-прежнему двумерен (с 1 в первом измерении), а выбор элементов возвращает двумерные объекты, поэтому поведение последовательности принципиально отличается от массивов.
- Объекты матриц переопределяют умножение, чтобы оно выполнялось как матричное умножение. Убедитесь, что вы понимаете это для функций, которые могут получать матрицы. Особенно с учетом того, что asanyarray(m) возвращает матрицу, когда m является матрицей.
- Объекты матриц переопределяют возведение в степень, чтобы оно выполнялось как возведение матрицы в степень. То же предупреждение о применении возведения в степень внутри функции, использующей asanyarray(...), чтобы получить объект массива, относится и к этому факту.
- Значение __array_priority__ по умолчанию для объектов матриц равно 10.0, и поэтому смешанные операции с массивами ndarray всегда приводят к матрицам.
-
Матрицы имеют специальные атрибуты, которые упрощают вычисления. Это
matrix.TВозвращает транспонированную матрицу. matrix.HВозвращает (комплексно) сопряжённую транспонированную матрицу. matrix.IВозвращает (мультипликативное) обратное значение для обратимой матрицы. matrix.AВозвращает selfкак объектndarray.
Предупреждение
Объекты матриц переопределяют умножение «*» и возведение в степень «**», соответственно, на матричное умножение и возведение в матричную степень. Если ваш подпрограмме могут передаваться подклассы, и вы не преобразуете их в массивы базового класса, то для того, чтобы убедиться, что вы выполняете правильную операцию для всех входных данных, необходимо использовать ufuncs multiply и power.
Класс матриц является подклассом ndarray в Python и может быть использован в качестве ссылки для построения собственного подкласса ndarray. Матрицы могут быть созданы из других матриц, строк и всего, что может быть преобразовано в ndarray. Название «mat» является псевдонимом для «matrix» в NumPy.
matrix | Возвращает матрицу из объекта типа массива или строки данных. |
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)
См. также
Примечание
Класс chararray существует для обратной совместимости с Numarray, его не рекомендуется использовать в новых разработках. Начиная с numpy 1.4, если необходимо создавать массивы строк, рекомендуется использовать массивы с типом dtype object_, string_ или unicode_, и использовать свободные функции в модуле numpy.char для быстрых векторных строковых операций.
Это расширенные массивы типа string_ или unicode_. Эти массивы наследуют от ndarray, но специально определяют операции +, *, и % на основе элементов (с широковещательной передачей). Эти операции недоступны для стандартных ndarray символьного типа. Кроме того, chararray имеет все стандартные методы string (и unicode), выполняемые на основе элементов. Возможно, самый простой способ создать chararray – использовать self.view(chararray), где self – ndarray с типом данных str или unicode. Однако chararray также может быть создан с использованием конструктора numpy.chararray или через функцию numpy.char.array:
chararray | Предоставляет удобный вид на массивы строковых и unicode-значений. |
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 не будет вызвано итератором. Существует несколько способов итерирования по массиву, которые могут быть полезны: стандартное итерирование, плоское итерирование и
-мерное перечисление.
Стандартное итерирование
Стандартный итератор объекта ndarray — это стандартный Python-итератор типа последовательности. Таким образом, когда сам объект массива используется как итератор. Стандартное поведение эквивалентно:
for i in range(arr.shape[0]):
val = arr[i]
Этот стандартный итератор выбирает подмассив размерности
из массива. Это может быть полезной конструкцией для определения рекурсивных алгоритмов. Для перебора всего массива требуется
циклов 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 | Итератор по массиву в виде одномерной последовательности. |
Как уже упоминалось, атрибут 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. Этот объект принимает
объекты в качестве входных данных и возвращает итератор, возвращающий кортежи, содержащие каждый элемент входных последовательностей в результате широковещательной рассылки.
>>> for val in broadcast([[1,0],[2,3]],[0,1]): ... print val (1, 0) (0, 1) (2, 0) (3, 1)
© 2008–2016 NumPy Developers
Licensed under the NumPy License.
https://docs.scipy.org/doc/numpy-1.10.1/reference/arrays.classes.html