NumPy ndarrays 真的是可变的吗?

这是我的第一个代码片段。运行时,它不会抛出断言错误。


import numpy as np



this_arr = np.ones(10)


next_arr = this_arr


next_arr *= 2


assert np.array_equal(this_arr, next_arr)

这是我的第二个代码片段。运行时,它会抛出一个断言错误。


import numpy as np



this_arr = np.ones(10)


next_arr = this_arr


next_arr = next_arr * 2


assert np.array_equal(this_arr, next_arr)

这种行为让我感到困惑。


我对第一个代码片段的理解是,我将名称初始化this_arr为指向某个内存位置的值。然后,当我初始化名称next_arr以指向相同内存位置的相同值时。因此,当我改变指向的值时next_arr,指向的值this_arr也应该改变。这种行为是 Ned Batchelder在此处创造的“Mutable-Presto-Chango” 。


但是,第二个代码片段不会以这种方式运行。起初,我认为也许*=运算符在操作符更改时不会以某种方式更改值在内存中的位置*。但是后来我回过头来看第一个片段,发现 和 的内存位置在this_arr这里next_arr也不同!鉴于此,程序如何“知道”更改值this_arr以匹配已更改的值next_arr?另外,为什么程序“不知道”更改第二个代码片段中的值?


编辑:作为后续问题:所以即使 next_arr 和 this_arr 有不同的内存位置,python 初始化的两者之间有一些潜在的联系?


幕布斯7119047
浏览 80回答 2
2回答

跃然一笑

我更喜欢谈论对象和引用,而不是价值观。所以我会把你的第一个代码描述为:这将创建一个ndarray对象,并将其(或对它的引用)分配给this_arr:this_arr = np.ones(10)并将相同的引用分配给next_arr:next_arr = this_arr所以next_arr和this_arr引用同一个对象。然后对数组对象进行“就地”更改。使用哪个名称并不重要。next_arr *= 2这两个名称仍然引用同一个数组对象。(在幕后做*=一些缓冲,但数组对象和数据缓冲区位置保持不变)。另一个可变的变化是next_arr[1] = 10(对于列表对象也是如此)。和next_arr = next_arr * 2乘法生成一个新的数组对象。那被分配给next_arr,打破了与先前引用对象(this_arr仍然引用)的任何链接。如果id(this_arr)和id(next_arr)相同,则引用该对象。大致id是一个位置 - 但与c. 但要注意随着时间的推移比较 id;它们可以被重复使用。arr.__array_interface__是另一个方便的工具。If 有一个data键告诉我们数组的底层数据缓冲区位于何处。但是要了解您需要了解数组的存储方式以及 和 之间的view区别copy。

哔哔one

当您初始化 next_arr=this_arr 时,它实际上所做的是将 this_arr 位置的值复制到 next_arr 的新位置。这是我对这段代码的理解,否则这种行为是不可能的
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python