The attributes of an array consist of shape, strides and the data.
a[3:10] is a view because it can use the original data buffer, and just use a different shape (7,) and a different start point in the buffer.
a[some_ind] cannot be a view because [0,5,6,24] is not a regular pattern. It can't be expressed as shape, strides and data pointer. There for is has to have its own data copy.
In [534]: a=np.zeros(25,int)
In [535]: np.info(a)
class: ndarray
shape: (25,)
strides: (4,)
itemsize: 4
aligned: True
contiguous: True
fortran: True
data pointer: 0xafa5cc0
...
In [536]: np.info(a[3:10])
class: ndarray
shape: (7,)
strides: (4,)
itemsize: 4
aligned: True
contiguous: True
fortran: True
data pointer: 0xafa5ccc # ccc v cc0
....
In [537]: np.info(a[[0,5,6,24]])
class: ndarray
shape: (4,)
strides: (4,)
itemsize: 4
aligned: True
contiguous: True
fortran: True
data pointer: 0xae9c038 # different
...
or looking at the data buffer pointer in decimal format:
In [538]: a.__array_interface__['data']
Out[538]: (184179904, False)
In [539]: a[3:10].__array_interface__['data']
Out[539]: (184179916, False) # 12 bytes larger
In [540]: a[[0,5,6]].__array_interface__['data']
Out[540]: (181099224, False)
Another way to put it is: the only alternative to copying elements of a, is to hang on the indexing array (or mask), and apply it each time you need those elements.