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]
_2
train[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 the
None values are concerned, a slice has a maximum of three data points: _start_, _stop_ and _step_. A
None value for any of these gives the default value, which is
0 for _start_, the length of the indexed object for _stop_, and
1 for _step. So
x[None:None:None] is equivalent to
x[0:len(x):1] which is equivalent to
x[: :]`。
有了这些知识,您应该有更多机会了解正在发生的事情。