numpy 切片和索引不同的结果

Posted

技术标签:

【中文标题】numpy 切片和索引不同的结果【英文标题】:numpy slicing and indexing different results 【发布时间】:2018-10-17 05:54:00 【问题描述】:

在通过任何切片、掩码或花式索引操作获得的numpy子数组中,都只是原始数组的视图,可以证明如下:

$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
'1.11.0'

>>> a = np.arange(3); a[:2] = 111; a
array([111, 111,   2])

>>> a = np.arange(3); a[a<2] = 111; a
array([111, 111,   2])

>>> a = np.arange(3); a[[0,1]] = 111; a
array([111, 111,   2])

在上面的例子中,整个子数组被赋值。但是,如果我们分配给子数组的一个元素,切片操作的结果仍然表现为视图,而屏蔽和花式索引操作的结果表现为独立副本:

>>> a = np.arange(3); a[:2][0] = 111; a
array([111,   1,   2])

>>> a = np.arange(3); a[a<2][0] = 111; a
array([0, 1, 2])

>>> a = np.arange(3); a[[0,1]][0] = 111; a
array([0, 1, 2])

这是 numpy 中的错误,还是设计使然?如果是有意为之,那么这种不一致的依据是什么?

【问题讨论】:

【参考方案1】:

这不是错误。只要您将切片对象传递给 Numpy 数组,返回的子数组就是原始项目的视图,这意味着即使切片分配或单个项目分配也会改变原始数组。但在其他情况下,返回的结果不是视图。事实上,它是所选切片的浅视图(副本),它只支持切片分配,就像 Python 中的其他可变对象一样。

documentation中也提到过:

[...] 与索引数组一样,返回的是数据的副本,而不是切片时的视图。

【讨论】:

好的,这意味着我还不太了解 Python 中赋值的工作原理。现在我的第一印象是 a[i] 的评估方式不同,具体取决于它是否出现在赋值运算符的左侧。重读文档,我发现对于用户定义的对象,赋值 object[expr] = ... 是通过 object.__setitem__ 评估的,而在其他情况下则使用 object.__getitem__。 @Leon 确实如此。这就是在 Python 中设置项目和获取项目的方式。

以上是关于numpy 切片和索引不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

NumPy 切片和索引

张量流中张量对象的非连续索引切片(高级索引,如numpy)

Numpy之ndarray的查询和修改 - 索引和切片

Numpy 切片和索引

NumPy索引切片

乐哥学AI_Python:Numpy索引,切片,常用函数