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

Numpy ndarray data ownership problem on reshape and view

我对 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 的“浅层”复制,所以 none 都有自己的数据。 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 变量,并将数据所有权留给之前旧的 a id 140289740187168.

问题是,既然旧的a已经被新的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 的值或数据存储位置的某种表示形式。

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

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

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

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

如果 numpy 'updated' 如您所建议的 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.base link 是 da,但没有 link 相反的