`ndarray.flags['OWNDATA']`、`ndarray.base`、`id(ndarray)`和`ndarray.__array_interface__['data']`有何不同?

问题描述 投票:0回答:1

我似乎在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)
实际上没有告诉我内存是否共享,那么它们告诉我什么?

python arrays numpy
1个回答
2
投票
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)

	
© www.soinside.com 2019 - 2024. All rights reserved.