NumPy切片和索引产生不同的结果

3
在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的一个bug吗?还是故意设计成这样呢?如果是故意设计成这种不一致性的话,有什么理由可以证明呢?
1个回答

2
这不是一个错误。只要你将切片对象传递给Numpy数组,返回的子数组就是原始项目的视图,这意味着即使是切片赋值或单个项目赋值也会更改原始数组。但在其他情况下,返回的结果不是一个视图。实际上它是所选切片的浅层视图(副本),仅支持像Python中的其他可变对象一样的切片赋值。 文档 中也提到了这一点:

[...] 与索引数组一样,返回的是数据的副本,而不是如片段中所得到的视图。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接