【问题标题】:Numpy ndarray data ownership problem on reshape and view重塑和查看 Numpy ndarray 数据所有权问题
【发布时间】:2021-01-16 19:03:22
【问题描述】:

我对 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 为140289740187168 的旧a

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

【问题讨论】:

    标签: python numpy ownership shallow-copy


    【解决方案1】:
    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, 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 按照您的建议“更新”了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,但没有其他方式的链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      相关资源
      最近更新 更多