2011-10-05 19 views
7

Ultimamente ho riscontrato problemi durante la creazione di matrici di oggetti Numpy utilizzando ad es.Matrici di oggetti Numpy

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

dove c è un'istanza di una classe complicata, e in alcuni casi Numpy tenta di accedere alcuni metodi di quella classe. Tuttavia, facendo:

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

risolve il problema. Sono curioso di sapere qual è la differenza tra questi due internamente. Perché nel primo caso Numpy potrebbe provare ad accedere ad alcuni attributi o metodi di c?

EDIT: Per la cronaca, ecco il codice di esempio che illustra il 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') 

Questo stampa getitem due volte. Fondamentalmente se __len__ è presente nella classe, allora questo è quando si può incorrere in comportamenti imprevisti.

+0

Non correlate, ma perché 'np.object' e non solo' object'? – JBernardo

+0

I due sono equivalenti ('' object == np.object'' restituisce '' True''), quindi questo non è correlato ai problemi che sto vedendo. – astrofrog

+1

@astrofog Ecco perché ho chiesto e ho detto che non era correlato. – JBernardo

risposta

9

Nel primo caso a = np.array([c], dtype=np.object), numpy non sa nulla della forma dell'array previsto.

Ad esempio, quando si definisce

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

quindi ci si aspetta numpy per determinare la forma in base alla lunghezza del d.

Quindi, allo stesso modo nel tuo caso, NumPy tenterà di vedere se len(c) è definito, e se lo è, per accedere agli elementi di c via c[i].

È possibile vedere l'effetto definendo una classe come la

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

Poi

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

produce

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

Al contrario, nel secondo caso

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

Quindi la forma di a è già stata determinata. Così numpy può semplicemente assegnare direttamente l'oggetto.

Tuttavia, in una certa misura questo è vero solo dal momento che a è un vettore. Se fosse stato definito con una forma diversa, gli accessi al metodo continueranno a verificarsi. Il seguente esempio sarà ancora chiamare ___getitem__ su una classe

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

rendimenti

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

questo è esattamente quello che mi serviva - in fondo se '' __len__'' è definito allora che è quando mi imbatto in problemi! – astrofrog

Problemi correlati