Python numpy,对ndarray.base的理解

Python numpy,对ndarray.base的理解,python,arrays,numpy,Python,Arrays,Numpy,我尝试了以下实验,以了解使用二维数组的numpy中的视图和副本 正如我们在下面看到的,切片创建了一个视图(a),使用整数列表进行索引创建了一个副本(c.base与arr不同,d.base为None)。根据我的理解,这是预期的行为 我不明白的是为什么c.base不是None,为什么c.flags.owndata是False。如果这是一个新的副本,为什么会发生这种情况 我注意到d视图的情况并非如此 import numpy as np arr = np.array([[1,2,4,8],

我尝试了以下实验,以了解使用二维数组的numpy中的视图和副本

正如我们在下面看到的,切片创建了一个视图(a),使用整数列表进行索引创建了一个副本(c.base与arr不同,d.base为None)。根据我的理解,这是预期的行为

我不明白的是为什么c.base不是None,为什么c.flags.owndata是False。如果这是一个新的副本,为什么会发生这种情况

我注意到d视图的情况并非如此

import numpy as np
arr = np.array([[1,2,4,8],
                [16, 32, 64, 128],
                [256, 512, 1024, 2048]])
print(arr)
print(arr.base)
print(arr.flags.owndata)
# [[   1    2    4    8]
#  [  16   32   64  128]
#  [ 256  512 1024 2048]]
# None
# True

# this is a view, identical base to arr.base
a = arr[:,1:3]
print(a)
print(a.base)
print(np.shares_memory(a, arr))
print(a.flags.owndata)
# [[   2    4]
#  [  32   64]
#  [ 512 1024]]
# [[   1    2    4    8]
#  [  16   32   64  128]
#  [ 256  512 1024 2048]]
# True
# False

# this is a copy, its own base, does not share memory with arr
c = arr[:,[1,3]]
print(c)
print(c.base)
print(np.shares_memory(c, arr))
print(c.flags.owndata)
# [[   2    8]
#  [  32  128]
#  [ 512 2048]]
# [[   2   32  512]
#  [   8  128 2048]]
# False
# False

# this is a copy, no base, does not share memory with arr
d = arr[[1,2], :]
print(d)
print(d.base)
print(np.shares_memory(d, arr))
print(d.flags.owndata)
# [[  16   32   64  128]
#  [ 256  512 1024 2048]]
# None
# False
# True


a
的情况是切片,其中始终返回一个引用。案例
c
d
包含索引,它总是返回一份副本。阅读更多关于它的信息

因此,
c
d
之间的区别是:

对于
c
,由于要复制所有行,但只选择列, 内部情况是,原始数组被转置并存储在新的ndarray中;然后删除未选中的列(新nd数组中的行)。然后返回一个转置(从打印
c
c.base
的结果可以看出这一点)

对于
d
,由于行是以不连续的方式选择的(该行的所有列)和(好的,取决于),因此直接从原始数组填充(复制,因此没有基)

编辑

根据信息,当索引不连续的行时(如
d
),将复制并堆叠单个行。 扩展这一思想,我假设对于不连续列(如
c
),执行三步操作更有意义:

  • 转置原始数组
  • 将所选列(现在是行)复制到新的nd数组中(必须存储为基)
  • 调换底座,然后返回

  • 我必须承认,我没有找到这方面的官方文档。

    对于
    a
    来说,情况是切片,其中总是返回一个引用。案例
    c
    d
    包含索引,它总是返回一份副本。阅读更多关于它的信息

    因此,
    c
    d
    之间的区别是:

    对于
    c
    ,由于要复制所有行,但只选择列, 内部情况是,原始数组被转置并存储在新的ndarray中;然后删除未选中的列(新nd数组中的行)。然后返回一个转置(从打印
    c
    c.base
    的结果可以看出这一点)

    对于
    d
    ,由于行是以不连续的方式选择的(该行的所有列)和(好的,取决于),因此直接从原始数组填充(复制,因此没有基)

    编辑

    根据信息,当索引不连续的行时(如
    d
    ),将复制并堆叠单个行。 扩展这一思想,我假设对于不连续列(如
    c
    ),执行三步操作更有意义:

  • 转置原始数组
  • 将所选列(现在是行)复制到新的nd数组中(必须存储为基)
  • 调换底座,然后返回

  • 我必须承认,我没有找到这方面的官方文件。

    你从哪里得到关于
    c
    案例中转置和放置的信息?相反,我认为它是创建一个(3,2)数组,并复制选定的列。使用
    strips
    numpy可以像索引行一样轻松地索引列。@hpaulj我认为
    strips
    可以帮助numpy确定行结束的界限。这是我的理解。让我觉得,
    在当前稳定版本的numpy中实现的花式索引
    要复杂得多。虽然他们有一个三步的过程,但它与我所提到的完全不同!对于大多数用户来说,
    c
    代码如何制作副本的细节并不重要。这一页,再加上对广播规则的熟悉,应该就足够了。你从哪里得到关于
    c
    案例中转置和放置的信息?相反,我认为它是创建一个(3,2)数组,并复制选定的列。使用
    strips
    numpy可以像索引行一样轻松地索引列。@hpaulj我认为
    strips
    可以帮助numpy确定行结束的界限。这是我的理解。让我觉得,
    在当前稳定版本的numpy中实现的花式索引
    要复杂得多。虽然他们有一个三步的过程,但它与我所提到的完全不同!对于大多数用户来说,
    c
    代码如何制作副本的细节并不重要。这个页面,再加上熟悉广播规则就足够了。
    b
    可以使用
    a
    databuffer,只需使用它自己的偏移量、形状和步幅即可。使用
    c
    d
    不能这样做-列或行已被单独选择(通过列表),因此它们必须有自己的数据缓冲区。如果您不能接受我们的word(或numpy索引文档),您可能需要阅读一些描述数组存储方式的numpy基础知识。我回答了作者最近提出的一些问题,他也试图理解索引。我使用
    \uuuu数组\u界面\uuuuu
    来识别
    视图
    复制
    (我认为这比
    base
    b
    可以通过使用
    a
    databuffer本身的偏移量、形状和步幅来提供更多信息。使用
    c
    d
    则无法做到这一点-列或行已被单独选择(通过列表),所以他们必须有自己的数据缓冲。如果你不能接受我们的话(或numpy索引文档),你可能需要阅读一些numpy bas