`y = x` 和 `y = x[:]` 与 x 是一个 numpy-ndarray 有什么区别?

Whats the difference between `y = x` and `y = x[:]` with x a numpy-ndarray?

我正在阅读 this 问题,关于不可变的 numpy 数组,并且在对其中一个答案的评论中有人表明,当使用 y = x[:] 而不是 y = x.

>>> import numpy as np
>>> x = np.array([1])
>>> y = x
>>> x.flags.writeable = False
>>> y[0] = 5
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    y[0] = 5
ValueError: assignment destination is read-only
>>> del x, y
>>> x = np.array([1])
>>> y = x[:]
>>> x.flags.writeable = False
>>> y[0] = 5
>>> x
array([5])

(Python 3.7.2, numpy 1.16.2)

这两者之间有什么区别,为什么在这种特定情况下它们的行为如此不同?

编辑:this 没有回答我的问题,因为它只询问使用列表的情况,我想知道为什么 numpy ndarray 显示这种特殊行为,有时取决于复制修改数据的方法会,有时不会引发错误。

y = x 只是添加对现有对象的另一个引用,这里没有复制。这只是将同一对象的另一个名称添加到本地名称空间中,因此它的行为在各个方面都与 x.

相同

y = x[:] 创建 numpy 数组的浅表副本。这是一个新的 Python 对象,但内存中的底层数组数据将是相同的。但是,标志现在是独立的:

>>> x = np.array([1])
>>> y = x[:]
>>> x.flags.owndata, y.flags.owndata
(True, False)

owndata 标志表明 y 只是对 x 数据的一个视图。在 x 上设置可写标志不会更改 y 的标志,因此 y 仍然持有对 x.

数据的可写视图
>>> x.flags.writeable, y.flags.writeable
(True, True)
>>> x.flags.writeable = False
>>> x.flags.writeable, y.flags.writeable
(False, True)

请注意,如果您在 复制 x 之前关闭 writeable 标志 ,那么副本也将取消设置可写标志,您将有一个只读的浅拷贝。