2013-03-28 8 views
8

Ich versuche langsam, den Unterschied zwischen view s und copy s in numpy, sowie Mutable vs unveränderliche Typen zu verstehen.Kopiert die Zuweisung mit erweiterter Indizierung Array-Daten?

Wenn ich Teil eines Arrays mit 'advanced indexing' zugreifen, soll es eine Kopie zurückgeben. Dies scheint wahr zu sein:

In [1]: import numpy as np 
In [2]: a = np.zeros((3,3)) 
In [3]: b = np.array(np.identity(3), dtype=bool) 

In [4]: c = a[b] 

In [5]: c[:] = 9 

In [6]: a 
Out[6]: 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 

Seit c ist nur eine Kopie, ist es nicht Daten gemeinsam nutzen und sie zu verändern mutiert nicht a. Allerdings ist es das, was mich verwirrt:

In [7]: a[b] = 1 

In [8]: a 
Out[8]: 
array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 

So scheint es, auch wenn ich Indexierung verwenden, die Zuweisung noch behandelt die Sache auf der linken Seite als Ansicht. Die a in Zeile 2 ist eindeutig das gleiche Objekt/Daten wie die a in Zeile 6, da die Mutation c hat keine Auswirkungen auf sie.

Also meine Frage: ist die a in Zeile 8 das gleiche Objekt/Daten wie zuvor (natürlich nicht die Diagonale) oder ist es eine Kopie? Mit anderen Worten, wurde a Daten auf die neue a kopiert, oder wurden seine Daten an Ort und Stelle mutiert?

Zum Beispiel ist es mag:

x = [1,2,3] 
x += [4] 

oder wie:

y = (1,2,3) 
y += (4,) 

Ich weiß nicht, wie für das, weil in jedem Fall zu prüfen, ist a.flags.owndataTrue. Bitte zögern Sie nicht, eine andere Frage zu formulieren oder zu beantworten, wenn ich darüber in verwirrender Weise nachdenke.

Antwort

6

Wenn Sie c = a[b] tun, wird a.__get_item__ mit b als einziges Argument aufgerufen, und was zurückgegeben wird, wird c zugewiesen.

Wenn Sie a[b] = c tun, a.__setitem__ mit b und c als Argumente genannt und was auch immer stillschweigend verworfen wird zurückgegeben.

Also, trotz der gleichen a[b] Syntax, machen beide Ausdrücke verschiedene Dinge.Sie könnten ndarray ableiten, diese zwei Funktionen überladen und sie sich anders verhalten. Wie standardmäßig in numpy, gibt ersteres eine Kopie zurück (wenn b ein Array ist), aber letzteres ändert a an Ort und Stelle.

+0

Ich denke, es lohnt sich, explizit in der Dokumentation darauf hinzuweisen, dass selbst eine erweiterte Indizierung, wenn sie als Lvalue verwendet wird, das ursprüngliche Array verändert. – vehsakul

3

Ja, es ist das gleiche Objekt. Hier ist, wie Sie überprüfen:

>>> a 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 
>>> a2 = a 
>>> a[b] = 1 
>>> a2 is a 
True 
>>> a2 
array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 

Zuordnung zu einem gewissen Ausdruck in Python ist nicht das gleiche wie nur den Wert dieses Ausdrucks zu lesen. Wenn Sie c = a[b] mit a[b] auf der rechten Seite des Gleichheitszeichens tun, gibt es ein neues Objekt zurück. Wenn Sie a[b] = 1 mit a[b] auf der linken Seite des Gleichheitszeichens tun, ändert es das ursprüngliche Objekt.

In der Tat kann ein Ausdruck wie a[b] = 1nicht ändern, welcher Name a gebunden ist. Der Code, der obj[index] = value handhabt, lernt nur das Objekt obj kennen, nicht, welcher Name für dieses Objekt verwendet wurde, also kann nicht geändert werden, worauf sich dieser Name bezieht.