2011-10-05 15 views
7

Recientemente me he encontrado con problemas al crear matrices de objetos Numpy usando p. Ej.matrices de objetos nudosos

a = np.array([c], dtype=np.object) 

donde c es una instancia de una clase complicada, y en algunos casos Numpy intenta acceder a algunos de los métodos de esa clase. Sin embargo, al hacer:

a = np.empty((1,), dtype=np.object) 
a[0] = c 

resuelve el problema. Tengo curiosidad sobre cuál es la diferencia entre estos dos internamente. ¿Por qué en el primer caso Numpy podría intentar acceder a algunos atributos o métodos de c?

EDIT: Para el registro, que aquí es el código de ejemplo que muestra el problema:

import numpy as np 

class Thing(object): 

    def __getitem__(self, item): 
     print "in getitem" 

    def __len__(self): 
     return 1 

a = np.array([Thing()], dtype='object') 

Esto muestra getitem dos veces. Básicamente, si __len__ está presente en la clase, entonces es cuando uno puede ejecutar un comportamiento inesperado.

+0

No relacionado, pero ¿por qué 'np.object' y no sólo' object'? – JBernardo

+0

Los dos son equivalentes ('' object == np.object'' devuelve '' True'') por lo que esto no está relacionado con los problemas que estoy viendo. – astrofrog

+1

@astrofog Es por eso que pregunté y dije que no estaba relacionado. – JBernardo

Respuesta

9

En el primer caso a = np.array([c], dtype=np.object), numpy no sabe nada sobre la forma de la matriz deseada.

Por ejemplo, cuando se define

d = range(10) 
a = np.array([d]) 

Entonces esperas numpy para determinar la forma en base a la longitud de d.

De manera similar en su caso, numpy intentará ver si len(c) está definido, y si es así, para acceder a los elementos de c a través de c[i].

Se puede ver el efecto mediante la definición de una clase como

class X(object): 
    def __len__(self): return 10 
    def __getitem__(self, i): return "x" * i 

Entonces

print numpy.array([X()], dtype=object) 

produce

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]] 

el contrario, en el segundo caso

a = np.empty((1,), dtype=np.object) 
a[0] = c 

Luego, la forma de a ya ha sido determinada. Así, Numpy puede asignar directamente el objeto.

Sin embargo, en cierta medida esto es cierto solo desde a es un vector. Si se hubiera definido con una forma diferente, los accesos a los métodos seguirán ocurriendo. La siguiente, por ejemplo, todavía se llame ___getitem__ en una clase

a = numpy.empty((1, 10), dtype=object) 
a[0] = X() 
print a 

vuelve

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]] 
+0

Esto es exactamente lo que necesitaba, básicamente, si '' __len__'' está definido, entonces eso es cuando me encuentro con problemas! – astrofrog

Cuestiones relacionadas