2009-04-21 12 views

Respuesta

95

No se debe pensar demasiado al respecto. En última instancia, es mejor para la salud mental y la longevidad del individuo.

La curiosa situación con los escalares de Numpy se debió al hecho de que no existe una manera elegante y consistente de degradar la matriz 1x1 a los tipos escalares. Aunque matemáticamente son la misma cosa, se manejan con un código muy diferente.

Si ha estado haciendo cualquier cantidad de código científico, en última instancia querría que cosas como max(a) funcionen en matrices de todos los tamaños, incluso escalares. Matemáticamente, esto es algo perfectamente sensato de esperar. Sin embargo, para los programadores esto significa que cualquier cosa que presente escalares en Numpy debería tener .simpe y .ndim attirbute, por lo que al menos los ufuncs no tienen que hacer una verificación de tipo explícita en su entrada para los 21 posibles tipos escalares en Numpy.

Por otro lado, también deberían funcionar con las bibliotecas de Python existentes que hace hacer comprobaciones de tipo explícitas en tipo escalar. Este es un dilema, ya que Numpy ndarray tiene que cambiar individualmente su tipo cuando se han reducido a un escalar, y no hay forma de saber si eso ha ocurrido sin que se haya verificado todo el acceso. De hecho, ir por esa ruta probablemente sería un poco ridículamente lento para trabajar con estándares de tipo escalar.

La solución del desarrollador Numpy es heredar tanto de los escalares de ndarray como de Python para su propio tipo de escala, de modo que todos los escalares también tengan .shape, .ndim, .T, etc. La matriz 1x1 seguirá allí, pero se desaconseja su uso si sabe que tratará con un escalar. Si bien esto debería funcionar bien en teoría, de vez en cuando todavía se podía ver a algunos lugares en los que se han perdido con el rodillo de pintura, y las entrañas feos está expuesta la vista de todos:

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

no hay realmente ninguna razón por la a[...] y a[()] debe devolver cosas diferentes, pero lo hace. Existen propuestas para cambiar esto, pero parece que se olvidó de terminar el trabajo para matrices de 1x1.

Un problema potencialmente más grande, y posiblemente no resolvable, es el hecho de que los escalares de Numpy son inmutables. Por lo tanto, "rociar" un escalar en un ndarray, matemáticamente la operación conjunta de colapsar una matriz en un escalar, es un PITA para implementar. No se puede crecer realmente un escalar Numpy, no puede, por definición, sea echado en una ndarray, a pesar de que newaxis misteriosamente trabaja en él:

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

En Matlab, con un crecimiento del tamaño de un escalar es un perfectamente aceptable y sin cerebro operación. En Numpy tienes que pegar jarring a = array(a) donde sea que pienses tienes la posibilidad de comenzar con un escalar y terminar con una matriz.Entiendo por qué Numpy tiene que ser así para jugar bien con Python, pero eso no cambia el hecho de que muchos nuevos mezcladores están profundamente confundidos al respecto. Algunos tienen memoria explícita de luchar con este comportamiento y, finalmente, perseverar, mientras que otros que están muy lejos se quedan generalmente con una cicatriz mental sin forma profunda que con frecuencia atormenta sus sueños más inocentes. Es una situación fea para todos.

+21

+1 para la introducción filosófica :-) –

+3

¿Has considerado una carrera en la escritura? – KobeJohn

+4

Mucho de esto parece ser la forma matlab de ver las cosas -_ "No se puede crecer un escalar Numpy" _ ni se puede crecer un np.array. Ser explícito sobre los tamaños hace que el comportamiento O (N^2) accidental sea más difícil. _ "no puede, por definición, incluirse en un ndarray" _ - eso es lo que 'np.asarray (escalar)' hace. _ "la matriz 1x1 ..." _ - pensar en cosas como inherentemente 2D, o como matrices, no es útil aquí – Eric

4

usted tiene que crear la matriz escalar un poco diferente:

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

Parece que scalars in numpy puede ser un concepto poco diferente de lo que se puede utilizar a partir de un punto de vista puramente matemático. Supongo que estás pensando en términos de matrículas escalares.

Cuestiones relacionadas