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

Vla*_*inu 5 python arrays numpy

我有以下一段代码:

import numpy as np
arr = np.arange(10)
slice = arr[2:5]
slice[:] = 12
print(arr)
slice = slice / 2
print(arr)
Run Code Online (Sandbox Code Playgroud)

输出将是:

[ 0  1 12 12 12  5  6  7  8  9]
[6. 6. 6.]
[ 0  1 12 12 12  5  6  7  8  9]
Run Code Online (Sandbox Code Playgroud)

所以第一次slice只是对一部分的引用,arr所以修改它也会改变数组,但第二次它变成了数组那部分的副本,修改它在arr. 为什么会发生这种情况?有什么slice = slice / 2不同?

use*_*699 9

对 Numpy 数组进行切片始终返回数组的视图(引用)。修改切片将修改原始数组。

在第二个示例中,您重新分配给 name s。这不会修改对象。创建一个数组来表示结果s // 2(与原始数组没有关系arr),然后s成为该新数组的名称。

s就地修改,请使用增强赋值运算符,例如//=, 或(如您已经看到的)切片赋值,例如 with [:]

>>> 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]))
Run Code Online (Sandbox Code Playgroud)

  • 我同意@Christoph。点 `slice = slice / 2` 是一个赋值,而 `slice[:] = slice / 2` 不是,已经表明,**原因**不清楚,尽管这正是提出的问题:“*是什么让`slice = slice / 2`不同*”。我可以避免写出错误的代码,但我没有一个清晰的认识(正如他们所说:*授人以鱼,他明天会饿。如果授人以鱼,他将永远富有*) [引用](https://en.wiktionary.org/wiki/give_a_man_a_fish_and_you_feed_him_for_a_day;_teach_a_man_to_fish_and_you_feed_him_for_a_lifetime))。 (3认同)
  • 这还不够清楚 - 你的第一句话暗示有一个“切片对象”你用作索引。这里是“2:5”。然后你声明你分配给这个“切片对象”,但它不会修改“对象”。请更清楚地区分名为“slice”的*变量*和您实际含义的对象,因为您想说的是在第二个示例中原始数组“arr”不会改变。 (2认同)