python - numpy 中如何实现多维数组切片/索引?

NumPy 数组的一大特色是您可以执行多维切片。我想知道它是如何实现的。让我列出到目前为止我的想法,然后希望有人可以填补空白,回答我的一些问题,并(可能)告诉我为什么我错了。

import numpy as np

arr = np.array([ [1, 2, 3], [4, 5, 6] ])

# retrieve the rightmost column of values for all rows
print(arr[:, 2])

# indexing a normal multidimensional list
not_an_arr = [ [1, 2, 3], [4, 5, 6] ]  
print(not_an_arr[:, 2])  # TypeError: indices must be integers or slices, not tuple

起初,[:, 2] 对我来说似乎违反了 Python 语法。如果我试图在 Python 中索引一个普通的多维列表,我会得到一个错误。当然,在实际阅读错误消息后,我意识到问题并不像我最初认为的语法那样,而是传入的对象类型。所以我得出的结论是[:, 2] 隐式地创建了一个元组,因此 [:, 2] 中真正发生的是 [(:, 2)]是这样吗?

接下来我尝试阅读 numpy.ndarray 类的源代码 linked to通过ndarray documentation ,不过C语言就这些了,我不精通,所以理解不了。

然后我注意到有 documentation for ndarray.__getitem__ .我希望这会引导我为类实现 __getitem__,因为我的理解是实现 __getitem__ 是应该定义索引对象的行为的地方。我希望我能够看到他们解压缩元组,然后使用其中包含的切片对象或整数对底层数据结构进行索引,但是这可能需要完成。

那么...让多维切片在 numpy 数组上起作用的幕后究竟发生了什么?

TLDR:如何为 numpy 数组实现多维数组切片?

最佳答案

我们可以用一个简单的类来验证你的第一级推论:

In [137]: class Foo():
     ...:     def __getitem__(self,arg):
     ...:         print(arg)
     ...:         return None
     ...: 
In [138]: f=Foo()
In [139]: f[1]
1
In [140]: f[::3]
slice(None, None, 3)
In [141]: f[,]
  File "<ipython-input-141-d115e3c638fb>", line 1
    f[,]
      ^
SyntaxError: invalid syntax

In [142]: f[:,]
(slice(None, None, None),)
In [143]: f[:,:3,[1,2,3]]
(slice(None, None, None), slice(None, 3, None), [1, 2, 3])

numpynp.lib.index_tricks.py 中使用这样的代码来实现像 np.r_ 这样的“函数” np.s_.它们实际上是使用索引语法的类实例。

值得注意的是它是逗号,比创建元组的 () 更重要:

In [145]: 1,
Out[145]: (1,)
In [146]: 1,2
Out[146]: (1, 2)
In [147]: ()          # exception - empty tuple, no comma
Out[147]: ()

这解释了语法。但实现细节留给对象类。 list(以及其他序列,如 string)可以处理整数和 slice 对象,但在给定元组时会出错。

numpy 对元组很满意。事实上,通过 getitem 传递元组是多年前添加到基础 Python 中的,因为 numpy 需要它。没有基类使用它(据我所知);但用户类可以接受元组,如我的示例所示。

关于numpy的细节,需要一些numpy数组存储的知识,包括shape的作用,strides 和数据缓冲区。我不确定我现在是否想参与其中。

几天前,我探索了一个多维索引示例,发现了一些我没有意识到(或从未见过记录)的细微差别

view of numpy with 2D slicing

对于我们大多数人来说,了解索引的操作方法比了解实现细节更重要。我怀疑有教科书、论文甚至 Wiki 页面都描述了“跨步”多维索引。 numpy 并不是唯一使用它的地方。

https://numpy.org/doc/stable/reference/arrays.indexing.html

这看起来像是对 numpy 数组的一个很好的介绍

https://ajcr.net/stride-guide-part-1/

https://stackoverflow.com/questions/68323196/

相关文章:

python - 多次拟合时 keras fit() 的历史

azure-devops - Azure Devops 管道 NPM 审计

schema - Protocol Buffer 架构无效。导入 "google/protobuf/

sql - 如何获得日期 + 时间的确定性计算值

rust - 如何正确处理 Warp 路由的错误

javascript - A 帧动画框在特定区域随机移动

python - 我的损失函数在训练期间没有得到更小的值

sass - Stylelint 禁用规则, "no-descending-specificity"

c - 为什么 GTK 4 报告 "assertion ' GTK_IS_WIDGET(部件 )'

reactjs - 如何在 primereact 中拥有主题切换器