组合索引操作时与 NumPy 数组的视图和副本混淆

Bra*_*wan 3 python arrays indexing numpy copy

>>> a = np.arange(12).reshape(3,4)

>>> a[0:3:2, :][:, [0,2]] = 100   ### the first time
>>> a  
array([[100, 1, 100, 3],
[ 4, 5, 6, 7],
[100, 9, 100, 11]])

>>> a[:, [0, 2]][0:3:2, :] = 0    ### second time
>>> a   
array([[100, 1, 100, 3],
       [ 4, 5, 6, 7],
       [100, 9, 100, 11]])
Run Code Online (Sandbox Code Playgroud)

我真的对 python 中的视图和副本感到困惑。上面的代码显示,数组a中给定的行和列第一次更改为100,从而更改了原始数组a。

但是,第二次原始数组没有改变。这是为什么?

MSe*_*ert 5

一个查找[:, [0,2]]因为它会返回副本高级索引。但是,当您分配给切片(例如array[whatever] = sth)时,它不会创建副本而是分配给指定的项目,即使它是高级索引。

所以第一个例子有效,因为第一个切片返回一个视图,然后它使用视图切片的赋值。

但是,第二个“失败”是因为您分配了副本的一部分(因为高级索引是常规索引之前完成的)。

区别主要是因为另一种方法负责将 ( __setitem__)设置为切片而不是获取 ( __getitem__) 这些切片。拆解你的语句:

a[0:3:2, :][:, [0,2]] = 100 

a.__getitem__((slice(0, 3, 2), slice(None))).__setitem__((slice(None), [0, 2]), 100)
|-------------- returns a view ------------|
Run Code Online (Sandbox Code Playgroud)

而第二个是:

a[:, [0,2]][0:3:2, :] = 0

a.__getitem__((slice(None), [0, 2])).__setitem__((slice(0, 3, 2), slice(None)), 0)
|--------- returns a copy ---------|
Run Code Online (Sandbox Code Playgroud)