理解numpy基础索引中高级索引+=操作修改原数组的原理
核心原因
你对「高级索引返回副本」的规则理解没错,但这个规则仅适用于x[索引数组]作为右值单独取值的场景,当它出现在增量赋值(+=、-=等)或普通赋值的左侧时,NumPy会额外执行结果写回原数组的步骤,并不会直接丢弃临时副本的运算结果。
实际执行步骤拆解
x[np.array([1, 1, 3, 1])] += 1的完整执行流程分为4步:
- 解析左值索引位置:NumPy首先记录当前索引对应的原数组x的下标位置列表:
[1, 1, 3, 1],用于后续写回结果。 - 读取值生成临时副本:按照下标列表取出x对应位置的值,生成和原数组不共享内存的临时数组
[10, 10, 30, 10],这一步和你验证的np.shares_memory结果一致,确实是副本。 - 执行增量运算:对临时副本做+1操作,得到运算后的临时数组
[11, 11, 31, 11]。 - 结果写回原数组:按照第一步记录的下标列表,将临时数组的元素依次赋值回原数组x的对应位置。这里要注意:重复下标对应的写入操作会覆盖之前的写入结果,因此下标1虽然出现了3次,但最终只会被赋值为11,而不是累加3次变成13。
常见误区说明
你之前的预想是把x[索引数组] += 1等价于:
temp = x[np.array([1, 1, 3, 1])] temp += 1
但这两种写法逻辑完全不同:后者是将x[索引数组]作为右值取值赋值给变量temp,后续temp的修改和原数组无关;而前者的增量赋值语法会被NumPy解析为x[索引数组] = x[索引数组] + 1,新增了赋值给左值的写回步骤,因此会修改原数组。
内容的提问来源于stack exchange,提问作者Trauer
相关产品推荐
相关产品推荐

