我似乎在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
现在
id
和 test
的 test2
(据说是内存中对象的地址)匹配,但 test3
不匹配,这与上述方法给出了完全相反的印象。
当然,这两种印象都是错误的,因为:
test.__array_interface__['data']
(209580688, False)
test2.__array_interface__['data']
(209580688, False)
test3.__array_interface__['data']
(209580688, False)
实际的缓冲区地址全部匹配。 确实:
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
的视图。ndarray.base
base
将指向另一个对象...或者 NumPy 将遵循该对象的
base
链并使用“根基”。有时是一种选择,有时是另一种选择。存在许多错误和向后兼容性问题。test2
不是
test
的视图。 test2
是
test
。它的 base
是 None
,因为它不是视图。test3
是
test
的视图,其base
设置为test
。ndarray.flags['OWNDATA']
test3
是一个视图,而
test2
不是,因为 test2
是
test
。id
id
给出对象的数字标识符,保证与生命周期与第一个对象重叠的任何对象的标识符不同。该函数不关心 NumPy 和视图;两个具有重叠生命周期的不同数组将具有不同的 ID,无论任何视图关系如何。
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)