Python 的优势之一是它对简单原则的统一应用。Numpy 索引,与 Python 中的所有索引一样,将单个参数传递给索引对象(即数组)的__getitem__方法,并且 numpy 数组是切片机制的主要理由之一(或至少是其早期用途之一)。
当我试图理解新行为时,我喜欢从一个具体且易于理解的示例开始,而不是 10x100 随机值,我将从一维 4 元素向量开始并工作到 3x4,它应该足够大了解发生了什么。
simple = np.array([1, 2, 3, 4])
train = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
解释器将这些显示为
array([1, 2, 3, 4])
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
该表达式simple[x]在底层等效于(也就是说解释器最终执行)simple.__getitem__(x)- 请注意此调用采用单个参数。
numpy 数组的__getitem__方法非常简单地使用整数实现索引:它从第一个维度中选择单个元素。如此,如此。simple[1]_2train[1]array([5, 6, 7, 8])
当__getitem__接收元组作为参数时(这是 Python 的语法解释表达式的方式array[x, y, z]),它将元组的每个元素作为索引应用于索引对象的连续维度。所以result = train[1, 2]是等价的(从概念上讲 - 代码在实现上更复杂)
temp = train[1] # i.e. train.__getitem__(1)
result = temp[2] # i.e. temp.__getitem__(2)
果然,我们发现它result出现在7. 你可以认为array[x, y, z]它等同于array[x][y][z].
现在我们可以添加切片。包含冒号的表达式可以被视为切片文字(我还没有看到更好的名称),解释器为它们创建切片对象。如文档所述,切片对象主要是三个值的容器,start,stop和slice,这取决于每个对象的__getitem__方法如何解释它们。您可能会发现这个问题有助于进一步了解切片。
有了你现在所知道的,你应该能够理解你的第一个问题的答案。
result = train[:-1, 1:-1]
将调用train.__getitem__切片的二元素元组。这相当于
temp = train[:-1]
result = temp[..., 1:-1]
第一条语句可以读作“设置temp为除最后一行之外的所有train”,第二个语句可以理解为“设置为result除第一列和最后一列之外的所有temp”。train[:-1]是
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
并将[1:-1]下标应用于该数组的第二维给出
array([[2, 3],
[6, 7]])
下标第一维上的省略号temp表示“通过所有内容”,因此the subscript expression[...] can be considered equivalent to[:] . As far as theNone values are concerned, a slice has a maximum of three data points: _start_, _stop_ and _step_. ANone value for any of these gives the default value, which is0 for _start_, the length of the indexed object for _stop_, and1 for _step. Sox[None:None:None] is equivalent tox[0:len(x):1] which is equivalent tox[: :]`。
有了这些知识,您应该有更多机会了解正在发生的事情。