<p>从<a href="http://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html" rel="nofollow noreferrer">SciPy cookbook</a>:</p>
<blockquote>
<p>The rule of thumb for creating a slice view is that the viewed elements can be addressed with offsets, strides, and counts in the original array. </p>
</blockquote>
<p>当你有一个像<code>x[[1, slice(None), 2]]</code>这样的索引时,你会得到一个视图,因为切片整个轴允许一定的偏移、跨距和计数来表示原始数组的切片。你知道吗</p>
<p>例如,对于<code>x = np.arange(27).reshape(3, 3, 3).copy()</code>,我们有:</p>
<pre><code>In [79]: x_view = x[1, :, 2] # or equivalently x[[1, slice(None), 2]]
In [80]: x_view
Out[80]: array([11, 14, 17])
In [81]: x_view.base
Out[81]:
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
</code></pre>
<p>然后我们可以使用<a href="https://github.com/numpy/numpy/blob/master/numpy/lib/utils.py#L186" rel="nofollow noreferrer">^{<cd3>}</a>(不是公共API的一部分,YMMV)来说明从原始数组获取切片的偏移量。你知道吗</p>
<pre><code>In [82]: np.byte_bounds(x_view)[0] - np.byte_bounds(x_view.base)[0]
Out[82]: 88
</code></pre>
<p>这是有意义的,因为在片中的第一个值11之前有11个8字节整数。NumPy使用一个公式来计算这个偏移量,这个公式可以<a href="https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#internal-memory-layout-of-an-ndarray" rel="nofollow noreferrer">see here</a>,使用原始数组的步长。你知道吗</p>
<pre><code>In [93]: (x.strides * np.array([1, 0, 2])).sum()
Out[93]: 88
</code></pre>
<p>我们切片中的步幅只是成为沿着我们切片的轴的<code>x</code>的步幅。i、 例如<code>x.strides[1] == x_view.strides[0]</code>。现在,偏移量、新的步长和计数加在一起就足够让NumPy从原始数组中查看切片了。你知道吗</p>
<pre><code>In [94]: x_view.strides
Out[94]: (24,)
In [95]: x_view.size
Out[95]: 3
</code></pre>
<p>最后,使用<code>x[[0, 1, 2]]</code>触发花哨索引的原因是,在没有全轴切片的情况下,通常不可能制定一些新的偏移量、字节顺序、跨距和计数,以便我们可以使用相同的基础数据查看切片。你知道吗</p>