关于重塑和视图的 Numpy ndarray 数据所有权问题

问题描述

我对 numpy 中的所有权机制感到困惑。

import numpy as np
a = np.arange(10)
a.flags.owndata     # True
id(a)               # 140289740187168

前四行很明显,变量a拥有id为140289740187168的数据。

b = a
c = a.view()
d = a.reshape((2,5))
print(b.flags.owndata,b.base,id(b.base)) # True None 94817978163056
print(c.flags.owndata,c.base,id(c.base)) # False [0 1 2 3 4 5 6 7 8 9] 140289740187168
print(d.flags.owndata,d.base,id(d.base)) # False [0 1 2 3 4 5 6 7 8 9] 140289740187168
id(None)                                   # 94817978163056

变量 c,d 都是 a 的“浅”拷贝,因此两者都没有自己的数据。 ba 并拥有数据(与 a 共享)。

a = a.view()
print(id(a))                               # 140289747003632
print(a.flags.owndata,a.base,id(a.base)) # False [0 1 2 3 4 5 6 7 8 9] 140289740187168

但是,将 a 的视图分配给 a 会创建一个 id 140289747003632 的新变量,并将数据所有权留给 id {{1} 的前一个a }.

问题是,由于旧的 140289740187168 已被新的 a 重载,将数据所有权转移到新的 a 会更合理。为什么旧的 a 仍然保留数据所有权?

解决方法

b = a

ba,只是同一个对象的不同名称。那甚至不是副本。

这些是views。视图是一个新数组,但它使用相同的数据缓冲区(如 base:

c = a.view()
d = a.reshape((2,5))

我喜欢用 __array_interface__ 查看数组的基本属性:

In [210]: a = np.arange(10)
In [211]: a.__array_interface__
Out[211]: 
{'data': (43515408,False),'strides': None,'descr': [('','<i8')],'typestr': '<i8','shape': (10,),'version': 3}

data[0]a 的值或数据存储位置的某种表示。

view 将具有相同的“数据”(具有可能的偏移量)。否则 view 有自己的 stridesshape。它是一个共享 base:

的新数组对象
In [212]: d = a.reshape((2,5))
In [213]: d.__array_interface__
Out[213]: 
{'data': (43515408,'shape': (2,5),'version': 3}

view 分配给 a 不会更改原始数组或数据缓冲区。原始的 a 数组对象及其数据缓冲区仍然存在于内存中。

In [214]: a = a.view()
In [216]: a.__array_interface__['data']
Out[216]: (43515408,False)

如果 numpy 按照您的建议“更新”了 a.base,它也必须针对原始 a 的所有视图(例如 d)更新它。>

In [218]: id(a)
Out[218]: 139767778126704
In [219]: id(a.base)
Out[219]: 139768132465328
In [220]: id(d.base)
Out[220]: 139768132465328

虽然 python 和 numpy 维护某种引用计数来确定哪些对象是垃圾,但 numpy 不维护 views 的记录。也就是说,虽然 d.based 链接到 a,但没有其他方式的链接。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...