web-dev-qa-db-fra.com

Pourquoi les tableaux 0d dans Numpy ne sont-ils pas considérés comme scalaires?

Un tableau 0d est sûrement scalaire, mais Numpy ne semble pas le penser ... est-ce que je manque quelque chose ou est-ce que je comprends mal le concept?

>>> foo = numpy.array(1.11111111111, numpy.float64)
>>> numpy.ndim(foo)
0
>>> numpy.isscalar(foo)
False
>>> foo.item()
1.11111111111
62
Salim Fadhley

Il ne faut pas trop y penser. C'est finalement meilleur pour la santé mentale et la longévité de l'individu.

La curieuse situation avec les types scalaires de Numpy était due au fait qu'il n'y avait pas de moyen gracieux et cohérent de dégrader la matrice 1x1 en types scalaires. Même s'ils sont mathématiquement la même chose, ils sont gérés par un code très différent.

Si vous avez fait n'importe quelle quantité de code scientifique, vous voudriez finalement que des choses comme max(a) fonctionnent sur des matrices de toutes tailles, même des scalaires. Mathématiquement, c'est une chose parfaitement sensée à attendre. Cependant, pour les programmeurs, cela signifie que tout ce qui présente des scalaires dans Numpy devrait avoir le .shape et .ndim attirbute, donc au moins les ufuncs n'ont pas à faire de vérification de type explicite sur son entrée pour les 21 types scalaires possibles dans Numpy.

D'autre part, ils devraient également fonctionner avec les bibliothèques Python existantes qui fait font des vérifications de type explicites sur le type scalaire. C'est un dilemme, car un ndarray Numpy a pour changer individuellement son type quand ils ont été réduits à un scalaire, et il n'y a aucun moyen de savoir si cela s'est produit sans qu'il ait fait des vérifications sur tous les accès. normes de type.

La solution du développeur Numpy consiste à hériter à la fois de ndarray et de scalaires Python pour son propre type scalaire, afin que tous les scalaires aient également .shape, .ndim, .T, etc., etc. La matrice 1x1 sera toujours là, mais son utilisation sera découragée si vous savez que vous aurez affaire à un scalaire. Bien que cela devrait fonctionner en théorie, vous pouvez parfois voir certains endroits où ils ont manqué avec le rouleau à peinture, et les entrailles laides sont exposé pour que tous voient:

>>> 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

Il n'y a vraiment aucune raison pour que a[...] Et a[()] retournent des choses différentes, mais c'est le cas. Il y a des propositions en place pour changer cela, mais on dirait qu'ils ont oublié de terminer le travail pour les baies 1x1.

Un problème potentiellement plus important et éventuellement non résolu est le fait que les scalaires Numpy sont immuables. Par conséquent, "pulvériser" un scalaire dans un ndarray, mathématiquement l'opération adjointe de réduire un tableau en un scalaire, est un PITA à mettre en œuvre. Vous ne pouvez pas réellement développer un scalaire Numpy, il ne peut pas par définition être converti en un ndarray, même si newaxis y travaille mystérieusement:

>>> 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])

Dans Matlab, augmenter la taille d'un scalaire est une opération parfaitement acceptable et sans cervelle. Dans Numpy, vous devez coller des secousses a = array(a) partout où vous pensez vous auriez la possibilité de commencer avec un scalaire et de vous retrouver avec un tableau. Je comprends pourquoi Numpy doit être de cette façon pour jouer à Nice avec Python, mais cela ne change pas le fait que de nombreux nouveaux commutateurs sont profondément confus à ce sujet. Certains ont un souvenir explicite de lutter contre ce comportement et finalement de persévérer, tandis que d'autres qui sont trop loin sont généralement laissés avec une profonde cicatrice mentale informe qui hante fréquemment leurs rêves les plus innocents. C'est une situation laide pour tous.

126
Tim Lin

Vous devez créer le tableau scalaire un peu différemment:

>>> x = numpy.float64(1.111)
>>> x
1.111
>>> numpy.isscalar(x)
True
>>> numpy.ndim(x)
0

Il ressemble à scalaires en numpy peut être un concept un peu différent de ce à quoi vous pouvez être habitué d'un point de vue purement mathématique. Je suppose que vous pensez en termes de matrices scalaires?

6
Jason Baker