Python索引不改变NumPy数组

3
import numpy as np
a = np.array([[0, 1, 2],
              [0, 1, 2],
              [1, 1, 2]])

a[[0, 1]] = 100  # Changed
print(a)
a[[0, 1]][0, 0] = 98  # Not Changed
print(a)
a[0:2][0, 0] = 99  # Changed
print(a)

输出结果为:

# first
[[100 100 100]
[100 100 100]
[  1   1   2]]

# second
[[100 100 100]
[100 100 100]
[  1   1   2]]

# third
[[ 99 100 100]
[100 100 100]
[  1   1   2]]

那么为什么第二种方法没有改变a数组,而第一种方法和第三种方法都可以呢?我已经谷歌了很多答案,但我还是不明白。
1个回答

6

情况比较复杂。

基本上,第一种和第二种情况是在进行高级索引,而第三种情况是在进行基本索引。NumPy关于高级索引的文档表明:

高级索引总是返回数据的副本(与基本切片相反,基本切片返回视图)。

因此,我们已经知道了第二种和第三种情况之间的区别。第二种情况基本上等同于

b = a[[0, 1]]
b[0, 0] = 98

自从高级索引创建了一个副本,b 不再与 a 相关联,更改也不会反映出来。在第三种情况下,我们有:
b = a[0:2]
b[0, 0] = 99

b 成为 a 的一个视图时(基本索引),b 中的更改将反映在 a 中。

那么第一种情况(Case 1)发生了什么?

本质上的区别是,您不能将其分解为赋值 b = ... 和后续的 setitem 操作。相反,您直接在索引结果上进行 setitem 操作,这不会创建副本(只有 getitem 操作副本)。因此,我们得到与第二种情况相同的行为。

以下说明了这一点:

第一种情况(Case 1) 等价于

setitem(a, [0, 1], 100)  # operates directly on a

案例2 等价于

setitem(
    getitem(a, [0, 1]),  # this is a copy
    [0, 0],
    98
)

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