In the docs, it says (emphasis mine):
Advanced indexing is triggered when the selection object, obj, is a
non-tuple sequence object, an ndarray (of data type integer or bool),
or a tuple with at least one sequence object or ndarray (of data type
integer or bool). There are two types of advanced indexing: integer
Also recognize thatwill trigger advanced indexing, whereas
will trigger basic slicing.
x[(1, 2, slice(None))]
>>> a = np.eye(4)
>>> a[(1, 2)] # basic indexing, as expected
>>> a[(1, np.array(2))] # basic indexing, as expected
>>> a[[1, 2]] # advanced indexing, as expected
array([[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.]])
>>> a[[1, np.array(2)]] # basic indexing!!??
There's an exception to that rule. The Advanced Indexing documentation section doesn't mention it, but up above, near the start of the Basic Slicing and Indexing section, you'll see the following text:
In order to remain backward compatible with a common usage in Numeric, basic slicing is also initiated if the selection object is any non-ndarray sequence (such as a list) containing slice objects, the Ellipsis object, or the newaxis object, but not for integer arrays or other embedded sequences.
a[[1, np.array(2)]] doesn't quite trigger basic indexing. It triggers an undocumented part of the backward compatibility logic, as described in a comment in the source code:
/* * Sequences < NPY_MAXDIMS with any slice objects * or newaxis, Ellipsis or other arrays or sequences * embedded, are considered equivalent to an indexing * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`) */
np.array(2) inside the list causes the list to be treated as if it were a tuple, but the result,
a[(1, np.array(2))], is still an advanced indexing operation. It ends up applying the
1 and the
2 to separate axes, unlike
a[[1, 2]], and the result ends up looking identical to
a[1, 2], but if you try it with a 3D
a, it produces a copy instead of a view.