For simple indexing of a 2d array both forms work:
In [28]: x = np.arange(6).reshape(2,3)
In [29]: x
Out[29]:
array([[0, 1, 2],
[3, 4, 5]])
In [30]: x[1,2]
Out[30]: 5
In [31]: x[1][2]
Out[31]: 5
For np.matrix
(which you probably shouldn't be using anyways) they aren't:
In [32]: X = np.matrix(x)
In [33]: X
Out[33]:
matrix([[0, 1, 2],
[3, 4, 5]])
In [34]: X[1,2]
Out[34]: 5
In [35]: X[1][2]
...
IndexError: index 2 is out of bounds for axis 0 with size 1
The two forms are not syntactically the same. [1][2]
first indexes with 1, and then indexes the result with 2. That's not the same as indexing once with both parameters.
In [36]: x[1]
Out[36]: array([3, 4, 5]) # (3,) shape
In [37]: X[1]
Out[37]: matrix([[3, 4, 5]]) # (1,3) shape
The error arises because np.matrix
returns another np.matrix
. So the next [2]
indexing will again be indexing the first dimension.
x[1]
is really short for x[1,:]
, that is, index the first dimension, and slice all the rest (or X[1,...]
to allow for 3d and higher). So x[1][2]
is really
temp = x[1,:]
temp[2]
or for the matrix case:
temp = X[1,:]
temp[2,:]
In other words, it is 2 indexing operations. It's a Python expression, not a specific numpy
usage.
When we index with lists or slices, the difference between the two forms becomes more significant, especially when setting values.
I encourage beginners to use the x[i,j]
form. Don't use x[1][2]
unless you really understand what is going on.
If needed I could get into how indexing is translated into calls to __setitem__
and __getitem__
.