2013-10-25 17 views
6

oggi ho utilizzato l'array NumPy per qualche calcolo e ha trovato uno strano problema, per esempio, si supponga ho già importato numpy.arange in ipython, e ho eseguito alcuni script come segue:serie affettare in NumPy

In [5]: foo = arange(10)              

In [8]: foo1 = foo[arange(3)]             

In [11]: foo1[:] = 0               

In [12]: foo 
Out[12]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [16]: foo2 = foo[0:3]              

In [19]: foo2[:]=0                

In [21]: foo 
Out[21]: array([0, 0, 0, 3, 4, 5, 6, 7, 8, 9]) 

sopra mostra che quando affetto la matrice per pippo [arange (3)], ho ottenuto una copia della sezione dell'array, ma quando ho affettato la matrice per pippo [0: 3], ho ottenuto un riferimento della sezione dell'array, quindi foo cambia con foo2. Poi ho pensato foo e foo2 dovrebbero avere lo stesso ID, ma che sembra non è vero

In [59]: id(foo) 
Out[59]: 27502608 

In [60]: id(foo2) 
Out[60]: 28866880 

In [61]: id(foo[0]) 
Out[61]: 38796768 

In [62]: id(foo2[0]) 
Out[62]: 38813248 

... 

ancora più strano, se continuo a controllare l'id di foo e foo2, non sono costanti, e, a volte, hanno fatto abbinarsi!

In [65]: id(foo2[0]) 
Out[65]: 38928592 

In [66]: id(foo[0])               
Out[66]: 37111504 

In [67]: id(foo[0]) 
Out[67]: 38928592 

qualcuno può spiegarlo un po '? Sono davvero confuso da questa caratteristica dinamica di pitone

grazie sacco

risposta

5
foo[arange(3)] 

non è una fetta. Gli elementi di arange(3) vengono utilizzati per selezionare gli elementi di foo per costruire un nuovo array. Poiché questo non può restituire in modo efficiente una vista (ogni elemento della vista dovrebbe essere un riferimento indipendente e le operazioni sulla vista richiederebbero un numero eccessivo di puntatori), restituisce una nuova matrice.

foo[0:3] 

è una sezione. Questo può essere fatto in modo efficiente come una vista; richiede solo la regolazione di alcuni limiti. Quindi, restituisce una vista.

id(foo[0]) 

foo[0] non si riferisce ad un oggetto Python specifico. Mantenere separati gli oggetti Python per ogni elemento dell'array sarebbe troppo costoso, annullando gran parte del beneficio di numpy. Invece, quando un'operazione di indicizzazione viene eseguita su un ndarray di numpy, numpy costruisce un nuovo oggetto da restituire. Otterrai un oggetto diverso con un ID diverso ogni volta.

+0

beh, allora perché id (foo) è anche diverso da id (foo2)? usano l'indirizzo del primo elemento come loro indirizzo? – shelper

+1

@shelper: foo non è foo2. Sebbene abbiano la stessa forma, dtype, ecc. E sebbene usino la stessa memoria per i loro elementi, sono oggetti diversi. Non credo che l'ID che si riceve abbia alcuna relazione con gli indirizzi degli elementi dell'array; è l'indirizzo di un'intestazione contenente metadati di array e un puntatore alla memoria utilizzata per gli elementi. – user2357112

+1

beh, penso di capire il problema, foo e foo2 sono entrambi oggetti python ben avvolti, id (foo) mostra solo l'indirizzo dell'oggetto python, non la memoria che contiene i dati, che in realtà può essere ottenuto da "foo". __array_interface __ ['data'] " – shelper