Ответ 1
Не стоит слишком думать об этом. Это в конечном счете лучше для психического здоровья и долголетия человека.
Любопытная ситуация с скалярными типами Numpy была обусловлена отсутствием грациозного и последовательного способа деградации матрицы 1x1 для скалярных типов. Хотя математически они одно и то же, они обрабатываются совсем другим кодом.
Если вы делали какой-либо научный код, в конечном итоге вы хотели бы, чтобы такие вещи, как max(a)
, работали над матрицами всех размеров, даже с скалярами. Математически это вполне разумная вещь. Однако для программистов это означает, что все, что представляет собой скаляр в Numpy, должно иметь .shape и .ndim attirbute, поэтому, по крайней мере, ufuncs не должны выполнять явную проверку типов на своем входе для 21 возможных скалярных типов в Numpy.
С другой стороны, они также должны работать с существующими библиотеками Python, которые выполняют явные проверки типов по скалярному типу. Это дилемма, поскольку Numpy ndarray должен индивидуально изменять свой тип, когда они были сведены к скаляру, и нет никакого способа узнать, произошло ли это, если у него нет проверок на весь доступ. Фактически, этот маршрут, вероятно, сделает смехотворно медленным работу со стандартами скалярного типа.
Решение разработчика Numpy должно наследовать как от скаляров ndarray, так и от Python для собственного скалярного типа, так что все скаляры также имеют .shape,.ndim,.T и т.д. и т.д. Матрица 1x1 все равно будет присутствовать, но ее использование будет обескуражено, если вы знаете, что будете иметь дело со скаляром. В то время как это должно работать нормально в теории, иногда вы все еще можете видеть некоторые места, где они пропустили с помощью роликового ролика, а уродливые внутренности открыты для всех, чтобы увидеть:
>>> from numpy import *
>>> a = array(1)
>>> b = int_(1)
>>> a.ndim
0
>>> b.ndim
0
>>> a[...]
array(1)
>>> a[()]
1
>>> b[...]
array(1)
>>> b[()]
1
Нет причин, по которым a[...]
и a[()]
должны возвращать разные вещи, но это так. Есть предложения, чтобы изменить это, но похоже, что они забыли закончить работу для массивов 1x1.
Потенциально большая и, возможно, неразрешимая проблема, заключается в том, что сканеры Numpy неизменяемы. Поэтому "распыление" скаляра в ndarray, математически сопряженная операция свертывания массива в скаляр, представляет собой PITA для реализации. Вы не можете на самом деле вырастить скаляр Numpy, он не может быть по определению включен в ndarray, хотя newaxis
таинственно работает над ним:
>>> b[0,1,2,3] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'numpy.int32' object does not support item assignment
>>> b[newaxis]
array([1])
В Matlab рост размера скаляра является вполне приемлемой и безмозглой операцией. В Numpy вам придется вставлять jarring a = array(a)
везде, где вы думаете, что у вас будет возможность начать со скаляра и в итоге получить массив. Я понимаю, почему Numpy должен быть таким образом, чтобы хорошо играть с Python, но это не меняет того факта, что многие новые переключатели глубоко смущены этим. У некоторых есть явная память о борьбе с этим поведением и, в конечном счете, настойчивом, в то время как другие, которые слишком далеко ушли, как правило, остаются с глубоким бесформенным умственным шрамом, который часто преследует их самые невинные мечты. Это ужасная ситуация для всех.