在语法上,这看起来像一个矛盾,但语义,你在这里做了两个非常不同的事情。在您定义的a
和b
中,您正在做advanced indexing,有时称为fancy indexing,它返回数据的副本。在c
的定义中,您正在执行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]
正如你可以看到,有很多不同可能的配置。首先,可以传递单个项目,或者可以传递项目的元组。其次,元组可以包含slice
对象,Ellipsis
对象,普通整数或numpy
数组。当传递只对象像int
,slice
,或Ellipsis
对象或None
(这是一样的numpy.newaxis
)
基本切片被激活。这些可以单独或以元组形式传递。下面介绍一下文档不得不说一下如何基本切片被激活:
当obj是切片对象发生
基本切片(由开始建造:停止:括号内的步骤符号),整数,或元组切片对象和整数。省略号和newaxis对象也可以与这些散布在一起。为了保持向后兼容的数字共同使用,基本切片也发起如果选择对象是任何序列(如列表)含有切片对象,省略号对象,或newaxis对象,但没有整数阵列或其它嵌入序列。当你经过一个numpy
阵列,仅包含整数或任何种类的含子序列,或含有一个阵列或子序列中的元组的非元组序列
高级索引被激活。
有关如何先进的索引和基本切片不同,请参阅该文档的细节(与上文)。但在这种特殊情况下,我很清楚发生了什么事情。它与使用部分索引时的以下行为有关:
部分索引的规则是结果的形状(或设置中要使用的对象的解释形状)是x将索引子空间替换为广播索引子空间。如果索引子空间彼此相邻,则广播索引空间直接替换x中的所有索引子空间。如果索引子空间是分开的(按切片对象),则广播的索引空间是第一个,后面是x的切片子空间。
在你的a
定义,它采用先进的索引,您可以有效地传递顺序[0, 1]
中的元组的第三个项目,因为没有广播发生(因为没有其他序列),一切都发生如预期。
在你的b
定义,也采用了先进的索引,则有效地传递序列,[0]
,第一项(其被转换成intp
阵列),和[0, 1]
,第三项。这两个项目一起播放,结果与第三个项目具有相同的形状。然而,自广播发生以来,我们面临着一个问题:我们在新形状元组中插入广播形状的位置?正如文档所说,
没有明确的地方放置在索引子空间中,因此它被固定在开头。
因此,广播产生的2
被移动到形状元组的开头,产生明显的转置。
感谢您的详细解释。这非常有帮助。切片+广播索引造成的奇怪行为仍然令人意想不到,难以编码。例如:start [0,:,np.arange(2)] = np.ones((5,2))似乎是合法的,但由于轴重新排序,它不是 – gbarter 2012-08-13 23:52:38
@gbarter为了保持原来的形状,你必须使用切片。即,这将工作:'开始[:1,:,np.arange(2)] = np.ones((5,2))' – jorgeca 2012-08-14 10:11:58