Стандартные подклассы массивов
Класс ndarray в NumPy — это «новый» встроенный тип Python. Поэтому от него можно унаследовать (в Python или C), если это необходимо. Таким образом, он может служить основой для многих полезных классов. Часто сложно решить, следует ли подклассифицировать объект массива или просто использовать ядро компонента массива как внутреннюю часть нового класса, и это может быть просто вопросом выбора. NumPy предоставляет несколько инструментов для упрощения взаимодействия нового объекта с другими объектами массива, и поэтому окончательный выбор может не иметь значения. Один из способов упростить вопрос — спросить себя, можно ли заменить интересующий вас объект одним массивом или он действительно требует двух или более массивов в своей основе.
Обратите внимание, что asarray всегда возвращает массив базового класса ndarray. Если вы уверены, что ваш способ использования объекта массива может обрабатывать любой подкласс ndarray, то asanyarray можно использовать, чтобы подклассы распространялись более гладко через вашу подпрограмму. В теории подкласс может переопределить любой аспект массива, и поэтому, при строгих правилах, asanyarray редко будет полезен. Однако большинство подклассов объекта массива не переопределяют некоторые аспекты объекта массива, такие как интерфейс буфера или атрибуты массива. Важный пример того, почему ваша подпрограмма может не справиться с произвольным подклассом массива, заключается в том, что матрицы переопределяют оператор «*» для выполнения матричного умножения вместо поэлементного.
Специальные атрибуты и методы
См. также
Numpy предоставляет несколько крючков, которые классы могут настроить:
-
class.__numpy_ufunc__(ufunc, method, i, inputs, **kwargs) -
Введено в версии 1.11.
Любой класс (подкласс 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__, описанный ниже.Примечание
Помимо ufuncs,
__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__(obj) -
Этот метод вызывается всякий раз, когда система внутренне выделяет новый массив из obj, где obj — подкласс (подтип)
ndarray. Он может использоваться для изменения атрибутов self после построения (например, для обеспечения 2-мерной матрицы) или для обновления метаданных из «родителя». Подклассы наследуют по умолчанию реализацию этого метода, который ничего не делает.
-
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, и поэтому смешанные операции с nd-массивами всегда производят матрицы.
-
Матрицы имеют специальные атрибуты, которые упрощают вычисления. Это
matrix.TВозвращает транспонированную матрицу. matrix.HВозвращает (комплексно) сопряженную транспонированную матрицу. matrix.IВозвращает (мультипликативное) обратное значение обратимой матрицы. matrix.AВозвращает матрицу как объект ndarray.
Предупреждение
Объекты матриц перезаписывают умножение, «*», и возведение в степень, «**», чтобы быть матричным умножением и матричной степенью соответственно. Если ваша подпрограмма может принимать подклассы, и вы не конвертируете в массивы базового класса, то вы должны использовать ufuncs multiply и power, чтобы убедиться, что вы выполняете правильную операцию для всех входов.
Класс матриц является подклассом Python ndarray и может использоваться в качестве ссылки на то, как создать свой собственный подкласс 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 со строковым или Unicode типом данных. Однако chararray также можно создать, используя конструктор numpy.chararray, или с помощью функции numpy.char.array:
chararray | Предоставляет удобный вид на массивы строковых и Unicode значений. |
core.defchararray.array(obj[, itemsize, ...]) | Создать chararray. |
Другое отличие от стандартного ndarray со строковым типом данных заключается в том, что 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 | Итератор по массиву в 1-D. |
Как упоминалось ранее, атрибут 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.11.0/reference/arrays.classes.html