gaa*_*kam 9 python arrays numpy copy
让我们引用numpy手册:https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing
当选择对象obj是非元组序列对象,ndarray(数据类型为integer或bool)或具有至少一个序列对象或ndarray(数据类型为integer或bool)的元组时,将触发高级索引.高级索引有两种类型:整数和布尔值.
高级索引始终返回数据的副本(与返回视图的基本切片形成对比).
然后对高级索引返回的内容进行操作永远不应该修改原始数组.事实上:
import numpy as np
arr = np.array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
indexes = np.array([3, 6, 4])
slicedArr = arr[indexes]
slicedArr *= 5
arr
Run Code Online (Sandbox Code Playgroud)
这打印:
array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
Run Code Online (Sandbox Code Playgroud)
但是,情况似乎并非总是如此.奇怪的是,如果我不保存[]
操作符返回的任何中间变量,我会以某种方式在原始数组上操作.请考虑这个例子:
import numpy as np
arr = np.array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
indexes = np.array([3, 6, 4])
arr[indexes] *= 5
arr
Run Code Online (Sandbox Code Playgroud)
这打印:
array([ 0, 10, 20, 150, 200, 50, 300, 70, 80, 90])
Run Code Online (Sandbox Code Playgroud)
我不抱怨.实际上,这对我来说是一个救生员.然而,我不明白为什么这样做,我真的很想理解这一点.
据我所知,一旦我写完,arr[indexes]
我就会创建一个数组的副本; 所以后续*= 5
应该在这个副本上运行,而不是在原始阵列上运行.但是,该计算的结果应该被丢弃,因为它不会被写入任何变量.
但显然我错了.
我的误会在哪里?
虽然声明
a = expr
Run Code Online (Sandbox Code Playgroud)
和
a[x] = expr
Run Code Online (Sandbox Code Playgroud)
看起来相似,它们实际上是根本不同的.第一个将名称'a'绑定到expr.第二个是或多或少等效到a.__setitem__(x, expr)
.什么__setitem__
实际上做的是最多谁实施,但传统的语义是更新容器对象a
在所指示的位置x
用expr
.特别是,没有a[x]
创建"代表"的中间对象.
只是为了完整性,a[x]
如果它不是语法上看起来像一个赋值或多或少相当的lhs a.__getitem__(x)
.
更新以回应后续问题(a[x] *= 5
执行时会发生什么?)让我们检测相关方法,以便我们可以看到发生了什么.下面__imul__
是就地乘法"魔法":
import numpy as np
class spy(np.ndarray):
def __getitem__(self, key):
print('getitem', key)
return super().__getitem__(key)
def __setitem__(self, key, value):
print('setitem', key)
return super().__setitem__(key, value)
def __imul__(self, other):
print('imul', other)
return super().__imul__(other)
a = spy((5, 5))
a[...] = 1
a[[1,2],[4,2]] *= 5
Run Code Online (Sandbox Code Playgroud)
打印:
setitem Ellipsis
getitem ([1, 2], [4, 2])
imul 5
setitem ([1, 2], [4, 2])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
230 次 |
最近记录: |