Reputation: 2040
So here's an oddity I noticed recently. In the code below I am creating either a 1D or 2D numpy array, extracting out one of the values from the array (position_3
), and then assigning the position I extracted from to a different value.
In the 1D case position_3
matches the originally assigned value in the array (i.e. looks like position_3
is a copy from the 1D array) while in the 2D cases position_3
changes upon changing the array (i.e. it looks like position_3
is a reference from the 2D array).
import numpy as np
print "Testing 1D array"
D1_array = np.array([0,1,2,3,4])
position_3 = D1_array[3]
D1_array[3] = 0
print "Value at position 3 in array: %i"%(D1_array[3]) #: 0
print "Value at position_3 variable: %i"%(position_3) #: 3
print "Testing 2D array"
D2_array = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14]])
position_3 = D2_array[3]
D2_array[3] = [0,0,0]
print "Value at position 3 in array: %s"%(str(D2_array[3])) #: [0,0,0]
print "Value at position_3 variable: %s"%(str(position_3)) #: [0,0,0]
I understand that everything is a reference in Python etc., but what I don't understand is why is this behavior inconsistent between 1D and 2D arrays? It's worth noting that the same comparison with Python lists yields the copy-like behaviour in both cases (i.e. in the 2D array - AKA a nested list - the position_3
variable remains [6,7,8]).
Upvotes: 1
Views: 214
Reputation: 879661
Per the docs on Basic Slicing and Indexing:
The simplest case of indexing with N integers returns an array scalar representing the corresponding item....
All arrays generated by basic slicing are always views of the original array. (my emphasis)
So indexing a 1D array with an integer returns an array scalar:
In [32]: D1_array = np.array([0,1,2,3,4])
In [33]: D2_array = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14]])
In [36]: D1_array[3]
Out[36]: 3
In [37]: type(D1_array[3]) # an array scalar
Out[37]: numpy.int64
If you assign position_3 = D1_array[3]
then position_3
holds the value of this array scalar. Modifying the original array with D1_array[3] = 0
does not affect the value of position_3
.
In contrast, indexing a 2D array with an integer returns a view:
In [38]: D2_array[3]
Out[38]: array([ 9, 10, 11])
In [40]: type(D2_array[3])
Out[40]: numpy.ndarray
In [42]: D2_array[3].base is D2_array
Out[42]: True
Modifying a view also alters the original array, and modifying the original array also affects the view.
Upvotes: 3