我似乎在 this 中遇到了 XY 问题关于如何判断数组是否共享相同内存的问题。我检查的方式是错误的,我不知道为什么。
举几个例子
test = np.ones((3,3))
test2 = np.array(test, ndmin = 2, copy = False)
test3 = np.array(test, ndmin = 3, copy = False)
首先,让我们检查它们是否使用 .base
共享内存
test2.base is test
False
test3.base is test
True
所以看起来 test3
正在与 test
共享数据,但 test2
却没有。事实上 test2.base is None => True
,我认为这意味着它是单独的内存(即副本)。
当我查看.flags
时,这种印象得到了加强。
test2.flags['OWNDATA']
True
test3.flags['OWNDATA']
False
似乎只有 test3
正在共享数据,而 test2
是一个副本。
但是如果我检查内置的 python
id(...)
id(test)
248896912
id(test2)
248896912
id(test3)
248897352
现在 test
和 test2
的 id
(据说是内存中对象的地址)匹配,但 test3
没有,这给人与上述方法完全相反的印象。
当然,这两种印象都是错误的,因为:
test.__array_interface__['data']
(209580688, False)
test2.__array_interface__['data']
(209580688, False)
test3.__array_interface__['data']
(209580688, False)
实际buffer addresses全部匹配。确实:
test[0,0] = 2
test, test2, test3
(array([[ 2., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]]),
array([[ 2., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]]),
array([[[ 2., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]]]))
所以,如果ndarray.base
、ndarray.flags['OWNDATA']
和id(ndarray)
实际上并没有告诉我如果内存是共享的,他们告诉我什么?
最佳答案
您的大部分困惑来自于 test2
是 test
和test3
是 test
的 View .
ndarray.base
如果将数组创建为另一个对象的 View ,则其 base
将指向另一个对象...或者 NumPy 将遵循该对象的 base
链并使用“根基”。有时是一种选择,有时是另一种选择。存在许多错误和向后兼容性问题。
test2
不是 test
的 View 。 test2
是 test
。它的base
是 None
因为它不是一个 View 。
test3
是 test
的 View ,及其 base
设置为test
.
ndarray.flags['OWNDATA']
如果数组是 View ,则设置此标志。如前所述,test3
是一个 View 和 test2
不是,因为test2
是 test
.
id
id
给出对象的数字标识符,保证与生命周期与第一个对象重叠的任何对象的标识符不同。该函数不关心 NumPy 和 View ;两个具有重叠生命周期的不同数组将具有不同的 ID,无论任何 View 关系如何。
test2
是 test
,所以它当然具有与自身相同的 ID。 test3
是一个具有重叠生命周期的不同对象,因此它具有不同的 ID。
ndarray.__array_interface__['data']
这是一个元组,其第一个元素是一个整数,表示数组第一个元素的内存地址。 (第二个元素对于这个问题并不重要。)test
, test2
,和test3
它们都使用相同的数据缓冲区,其第一个元素具有相同的偏移量,因此它们在这里给出相同的值。但是,共享内存的两个数组并不总是具有相同的值,因为它们可能不具有相同的第一个元素:
>>> import numpy
>>> x = numpy.arange(5)
>>> y = x[1:]
>>> z = x[:-1]
>>> x.__array_interface__['data']
(39692208L, False)
>>> y.__array_interface__['data']
(39692212L, False)
>>> z.__array_interface__['data']
(39692208L, False)
关于python - `ndarray.flags[' OWNDATA' ]`, ` ndarray.base`、 `id(ndarray)` 和 `ndarray.__array_interface__[' data']` 有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47449516/