2013-10-25 15 views
6

heute Schneiden verwendete ich die numpy Array für einige Berechnung und fand ein seltsames Problem, zum Beispiel gehe ich davon aus importierten numpy.arange bereits in IPython, und ich laufen einige Skripte wie folgt:Array 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]) 

oben zeigt, dass, wenn ich das Array durch foo [arange (3)] schneiden, ich eine Kopie des Array-Slice, aber wenn ich das Array durch foo [0: 3] Slice, bekam ich so eine Referenz des Array-Slice foo ändert sich mit foo2. Dann dachte ich, foo und foo2 sollte die gleiche ID haben, aber das scheint nicht der Fall ist

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 

... 

noch seltsamer, wenn ich die ID von foo und foo2 halten Kontrolle, sie nicht konstant sind, und manchmal haben sie passen zueinander!

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

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

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

kann jemand das ein wenig erklären? Ich bin wirklich von dieser dynamischen Eigenschaft von Python

dank verwirrt alot

Antwort

5
foo[arange(3)] 

nicht eine Scheibe ist. Die Elemente von werden verwendet, um Elemente von foo auszuwählen, um ein neues Array zu konstruieren. Da dies eine Sicht nicht effizient zurückgeben kann (jedes Element der Sicht muss eine unabhängige Referenz sein, und Operationen in der Sicht müssen viel zu viele Zeiger folgen), wird ein neues Array zurückgegeben.

foo[0:3] 

ist ein Stück. Dies kann effizient als eine Ansicht durchgeführt werden; es erfordert nur das Anpassen einiger Grenzen. So gibt es eine Ansicht zurück.

id(foo[0]) 

foo[0] bezieht sich nicht auf ein bestimmtes Python-Objekt. Separate Python-Objekte für jedes Array-Element zu behalten wäre viel zu teuer, was den Nutzen von numpy zunichte machen würde. Wenn eine Indexierungsoperation für ein numpy ndarray ausgeführt wird, erstellt numpy stattdessen ein neues Objekt, das zurückgegeben werden soll. Sie erhalten jedes Mal ein anderes Objekt mit einer anderen ID.

+0

gut, warum ist ID (foo) auch anders als id (foo2)? verwenden sie die Adresse des ersten Elements als ihre Adresse? – shelper

+1

@shelper: foo ist nicht foo2. Obwohl sie die gleiche Form, dtype usw. haben, und obwohl sie den gleichen Speicher für ihre Elemente verwenden, sind sie unterschiedliche Objekte. Ich glaube nicht, dass die ID, die Sie erhalten, irgendeine Beziehung zu den Adressen der Array-Elemente hat; Es ist die Adresse eines Headers, der Array-Metadaten und einen Zeiger auf den Speicher enthält, der für die Elemente verwendet wird. – user2357112

+1

Nun, ich denke, ich verstehe das Problem, Foo und Foo2 sind beide gut eingewickelt Python-Objekt, ID (foo) zeigen nur die Adresse des Python-Objekts, nicht der Speicher, der die Daten enthält, die tatsächlich von "foo. __array_interface __ ['data'] " – shelper