python - `ndarray.flags[' OWNDATA' ]`, ` ndarray.base`、 `id(ndarray)` 和 `ndarray.__array_interface__[' data']` 有什么不同?

标签 python arrays numpy

我似乎在 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

现在 testtest2id(据说是内存中对象的地址)匹配,但 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.basendarray.flags['OWNDATA']id(ndarray)实际上并没有告诉我如果内存是共享的,他们告诉我什么

最佳答案

您的大部分困惑来自于 test2 testtest3test 的 View .

ndarray.base

如果将数组创建为另一个对象的 View ,则其 base将指向另一个对象...或者 NumPy 将遵循该对象的 base链并使用“根基”。有时是一种选择,有时是另一种选择。存在许多错误和向后兼容性问题。

test2不是 test 的 View 。 test2 test 。它的baseNone因为它不是一个 View 。

test3test 的 View ,及其 base设置为test .

ndarray.flags['OWNDATA']

如果数组是 View ,则设置此标志。如前所述,test3是一个 View 和 test2不是,因为test2 test .

id

id给出对象的数字标识符,保证与生命周期与第一个对象重叠的任何对象的标识符不同。该函数不关心 NumPy 和 View ;两个具有重叠生命周期的不同数组将具有不同的 ID,无论任何 View 关系如何。

test2test ,所以它当然具有与自身相同的 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/

相关文章:

Python:如何将多进程链接到多进度条

c - 使用二维数组,我的数组没有出现

python - 面临 ImportError : No module named discriminant_analysis

python - 文件 "E:\python\lib\re.py",第 229 行,在 finditer 中返回 _compile(pattern, flags).finditer(string) TypeError : expected string or bytes-like object

Python Pygame 蛇苹果在障碍物内生成

Python BeautifulSoup findAll 通过 "class"属性

php 结果集到数组

java - 这个数组如何打印这个条形图?

python - 为什么 numpy 比我的 c/c++ 代码对 float 组求和更快?

python - Theano:如何获取元素为矩阵的 "matrix outer product"