关于NumPy数组切片何时是引用,何时是副本的困惑

ff29svar  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(68)

如果我尝试以下操作:

>>> import numpy as np
>>> arr = np.arange(10)
>>> s = arr[2:5]
>>> s[:] = 12
>>> s, arr
(array([12, 12, 12]), array([ 0,  1, 12, 12, 12,  5,  6,  7,  8,  9]))
>>> s = s // 2
>>> s, arr
(array([6., 6., 6.]), array([ 0,  1, 12, 12, 12,  5,  6,  7,  8,  9]))

似乎第一次围绕s只是引用了arr的一部分,所以修改它也会改变数组(一些12出现在arr中);但是第二次,s已经成为该部分数组的副本,而arr不受影响(arr中的12不会成为6)。
为什么会发生这种情况?s = s // 2有什么不同?

njthzxwz

njthzxwz1#

切片Numpy数组总是返回数组的视图(引用)。修改切片将修改原始数组。
在第二个示例中,您重新分配名称s。它不会修改对象。创建一个数组来表示s // 2的结果-它与原始arr没有**关系-然后s成为该新数组的名称。
要就地修改s,可以使用一个增广赋值运算符,比如//=,或者(正如你已经看到的)像[:]那样的切片赋值:

>>> import numpy as np
>>> arr = np.arange(10)
>>> s = arr[2:5]
>>> s, arr
(array([2, 3, 4]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
>>> s[:] = 12 # modifies the slice, and therefore the original
>>> s, arr
(array([12, 12, 12]), array([ 0,  1, 12, 12, 12,  5,  6,  7,  8,  9]))
>>> s //= 2 # modifies the slice, and therefore the original
>>> s, arr
(array([6, 6, 6]), array([0, 1, 6, 6, 6, 5, 6, 7, 8, 9]))
>>> s = s // 2 # makes a new slice (and reassigns the name), so the original is untouched
>>> s, arr
(array([3, 3, 3]), array([0, 1, 6, 6, 6, 5, 6, 7, 8, 9]))
4szc88ey

4szc88ey2#

使用[:]将值赋回:

>>> arr = np.arange(10)
>>> s = arr[2:5]
>>> s[:] = 12
>>> print(arr)
[ 0  1 12 12 12  5  6  7  8  9]
>>> s[:] = s // 2
>>> print(arr)
[0 1 6 6 6 5 6 7 8 9]

相关问题