arr = np.arange(0,11)
slice_of_arr = arr[0:6]
slice_of_arr[:]=99
# slice_of_arr returns
array([99, 99, 99, 99, 99, 99])
# arr returns
array([99, 99, 99, 99, 99, 99, 6, 7, 8, 9, 10])
Run Code Online (Sandbox Code Playgroud)
如上所示,您不能直接更改值slice_of_arr,因为它是一个视图arr,而不是一个新变量.
我的问题是:
.copy然后分配价值不是很乏味吗?.copy?如何更改NumPy的默认行为?谈论ndarray子类和钩子,例如__array_wrap__. np.array采用copy参数,强制结果为副本,即使其他考虑因素不需要它。 ravel返回一个视图,flatten一个副本。ndarray因此,构造一个强制复制的子类可能是可能的,而且可能不太困难。它可能涉及修改像__array_wrap__.
或者也许修改一下.__getitem__方法。索引涉及slice_of_arr = arr[0:6]对 的调用__getitem__。因为ndarray这是已编译的,但对于屏蔽数组,您可以使用 python 代码作为示例:
/usr/lib/python3/dist-packages/numpy/ma/core.py
Run Code Online (Sandbox Code Playgroud)
这可能很简单
def __getitem__(self, indx):
"""x.__getitem__(y) <==> x[y]
"""
# _data = ndarray.view(self, ndarray) # change to:
_data = ndarray.copy(self, ndarray)
dout = ndarray.__getitem__(_data, indx)
return dout
Run Code Online (Sandbox Code Playgroud)
但我怀疑,当您开发并完全测试这样的子类时,您可能会爱上默认的无复制方法。虽然这种“查看-v-复制”业务困扰了许多新用户(尤其是来自 MATLAB 的用户),但我还没有看到有经验的用户对此提出抱怨。查看其他 numpy SO 问题;你不会看到很多copy()电话。
即使是普通的 Python 用户也会问自己引用或切片是否是副本,以及某些内容是否可变。
例如列表:
In [754]: ll=[1,2,[3,4,5],6]
In [755]: llslice=ll[1:-1]
In [756]: llslice[1][1:2]=[10,11,12]
In [757]: ll
Out[757]: [1, 2, [3, 10, 11, 12, 5], 6]
Run Code Online (Sandbox Code Playgroud)
修改项目切片内的项目会修改原始列表中的同一项目。与 相比numpy,列表切片是一个副本。但这是一个浅拷贝。您必须付出额外的努力才能进行深复制 ( import copy)。
/usr/lib/python3/dist-packages/numpy/lib/index_tricks.py包含一些索引功能,旨在使某些索引操作更加方便。有几个实际上是具有自定义方法的类或类实例__getitem__。它们还可以作为如何自定义切片和索引的模型。