2016-03-17 18 views
6

Ich brauche eine gute Erklärung (Referenz), um NumPy Slicing innerhalb (für) Schleifen zu erklären. Ich habe drei Fälle.Slicing ein NumPy Array innerhalb einer Schleife

def example1(array): 
    for row in array: 
     row = row + 1 
    return array 

def example2(array): 
    for row in array: 
     row += 1 
    return array 

def example3(array): 
    for row in array: 
     row[:] = row + 1 
    return array 

Ein einfacher Fall:

ex1 = np.arange(9).reshape(3, 3) 
ex2 = ex1.copy() 
ex3 = ex1.copy() 

Rückkehr:

>>> example1(ex1) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

>>> example2(ex2) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

>>> example3(ex3) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

Es kann, dass das erste Ergebnis unterscheidet sich von der zweiten und dritten gesehen werden.

+2

Verwandte Frage, hoffe das hilft http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python/15376520#15376520 – Thiru

Antwort

4

Erstes Beispiel:

Sie eine Zeile extrahieren und fügen Sie 1 zu. Dann hast du neu definiert die Zeigerrow aber nicht was die array enthält! Dies hat keine Auswirkungen auf das ursprüngliche Array.

Zweites Beispiel:

Sie machen einen in-Place-Betrieb - offensichtlich ist dies das ursprüngliche Array auswirken wird - solange es ein Array ist.

Wenn Sie waren eine doppelte Schleife tun würde es nicht mehr funktionieren:

def example4(array): 
    for row in array: 
     for column in row: 
      column += 1 
    return array 

example4(np.arange(9).reshape(3,3)) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

dies nicht funktioniert, weil Sie nicht nennen np.ndarray ‚s __iadd__ (um die Daten, die die Array-Punkte zu ändern, um) aber der Python int 's __iadd__. Dieses Beispiel funktioniert also nur, weil Ihre Zeilen nummerische Arrays sind.

Drittes Beispiel:

row[:] = row + 1 dies als so etwas wie row[0] = row[0]+1, row[1] = row[1]+1, ... interpretiert wieder das funktioniert am Platz, so das das ursprüngliche Array auswirkt.

Bottom Line

Wenn Sie auf veränderbare Objekte arbeiten, wie list s oder np.ndarray Sie müssen vorsichtig sein, was Sie ändern. Solch ein Objekt nur Punkte zu, wo die tatsächlichen Daten im Speicher gespeichert ist - so ändert sich Zeiger (example1) hat keinen Einfluss auf die gespeicherten Daten. Sie müssen dem Zeiger folgen (entweder direkt durch [:] (example3) oder indirekt mit array.__iadd__ (example2)), um die gespeicherten Daten zu ändern.

3

Im ersten Code machen Sie nichts mit der neuen berechneten Zeile; Sie binden den Namen row erneut, und es besteht keine Verbindung mehr zum Array.

In der zweiten und dritten, nicht binden, aber zuweisen Sie die alte Variable. Mit += wird eine interne Funktion aufgerufen, die je nach Objekttyp variiert. Siehe Links unten.

Wenn Sie auf der rechten Seite row + 1 schreiben, wird ein neues Array berechnet. Im ersten Fall geben Sie python den Namen namerow (und vergessen Sie das ursprüngliche Objekt, das vorher row genannt wurde).Und in der dritten wird das neue Array in die Scheibe des alten row geschrieben.

Für weitere Informationen folgen Sie dem Link des Kommentars zu der Frage von @Thiru oben. Oder lesen Sie über assignment and rebinding in general...