从语法上来说,这看起来像是不一致的,但从语义上来说,你在这里做了两件截然不同的事情。在你的定义中a
and b
, 你正在做的高级索引 http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing,有时称为花式索引 https://www.numpy.org/devdocs/user/quickstart.html#fancy-indexing-and-index-tricks,它返回数据的副本。在你的定义中c
, 你正在做的基本切片 http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#basic-slicing,它返回数据的视图。
为了区分其中的差异,有助于理解索引如何传递给 python 对象。这里有些例子:
>>> class ShowIndex(object):
... def __getitem__(self, index):
... print index
...
>>> ShowIndex()[:,:]
(slice(None, None, None), slice(None, None, None))
>>> ShowIndex()[...,:]
(Ellipsis, slice(None, None, None))
>>> ShowIndex()[0:5:2,::-1]
(slice(0, 5, 2), slice(None, None, -1))
>>> ShowIndex()[0:5:2,np.arange(3)]
(slice(0, 5, 2), array([0, 1, 2]))
>>> ShowIndex()[0:5:2]
slice(0, 5, 2)
>>> ShowIndex()[5, 5]
(5, 5)
>>> ShowIndex()[5]
5
>>> ShowIndex()[np.arange(3)]
[0 1 2]
正如你所看到的,有many不同的可能配置。首先,可以传递单个项目,或者可以传递项目的元组。其次,元组可能包含slice
物体,Ellipsis
对象、普通整数或numpy
数组。
当您通过时会激活基本切片only像这样的物体int
, slice
, or Ellipsis
物体,或None
(这与numpy.newaxis
)。这些可以单独传递或以元组形式传递。以下是文档关于如何激活基本切片的说明:
当 obj 是切片对象(由括号内的 start:stop:step 表示法构造)、整数或切片对象和整数的元组时,会发生基本切片。省略号和 newaxis 对象也可以散布在这些对象中。为了保持与数值中常见用法的向后兼容,如果选择对象是包含切片对象、省略号对象或 newaxis 对象但没有整数数组或其他对象的任何序列(例如列表),也会启动基本切片。嵌入序列。
当您通过numpy
数组、仅包含整数或包含任何类型的子序列的非元组序列,或者包含数组或子序列的元组。
有关高级索引和基本切片有何不同的详细信息,请参阅文档(链接到上面)。但在这个特殊情况下,我很清楚发生了什么。它与使用部分索引时的以下行为有关:
部分索引的规则是结果的形状(或设置中要使用的对象的解释形状)是 x 的形状,其中索引子空间替换为广播索引子空间。如果索引子空间彼此相邻,则广播索引空间直接替换 x 中的所有索引子空间。如果索引子空间被分隔(通过切片对象),则首先是广播索引空间,然后是 x 的切片子空间。
在你的定义中a
,它使用高级索引,您可以有效地传递序列[0, 1]
作为元组的第三项,并且由于没有发生广播(因为没有其他序列),所以一切都按预期发生。
在你的定义中b
,还使用高级索引,您可以有效地通过two序列,[0]
,第一项(被转换为intp
数组),以及[0, 1]
,第三项。这两个项目一起广播,结果与第三个项目具有相同的形状。然而,由于广播已经发生,我们面临着一个问题:我们在新形状元组中的哪里插入广播形状?正如文档所说,
索引子空间中没有明确的位置可以放置,因此它被附加到开头。
So the 2
广播的结果被移动到形状元组的开头,产生明显的转置。