在語法上,這看起來像一個矛盾,但語義,你在這裏做了兩個非常不同的事情。在您定義的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