是否使用高级索引复制数组数据?

ask*_*han 13 python numpy copy

我正在慢慢地尝试理解n viewcopys中的s和s 之间的区别,以及可变类型和不可变类型.

如果我使用'高级索引'访问数组的一部分,则应该返回一个副本.这似乎是真的:

In [1]: import numpy as np
In [2]: a = np.zeros((3,3))
In [3]: b = np.array(np.identity(3), dtype=bool)

In [4]: c = a[b]

In [5]: c[:] = 9

In [6]: a
Out[6]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
Run Code Online (Sandbox Code Playgroud)

由于c只是一个副本,它不共享数据,更改它不会变异a.然而,这让我感到困惑:

In [7]: a[b] = 1

In [8]: a
Out[8]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
Run Code Online (Sandbox Code Playgroud)

因此,似乎即使我使用高级索引,分配仍然将左侧的东西视为视图.显然a,第2行是与a第6行相同的对象/数据,因为变异c对它没有影响.

所以我的问题是:a第8行是与以前相同的对象/数据(当然不算对角线)还是副本?换句话说,是将a数据复制到新的a,还是将其数据变异?

例如,它是这样的:

x = [1,2,3]
x += [4]
Run Code Online (Sandbox Code Playgroud)

或者喜欢:

y = (1,2,3)
y += (4,)
Run Code Online (Sandbox Code Playgroud)

我不知道如何检查这个,因为无论哪种情况,a.flags.owndata都是True.如果我以一种令人困惑的方式思考这个问题,请随时详细说明或回答不同的问题.

Jai*_*ime 9

当你这样做时c = a[b],a.__get_item__b作为唯一参数调用,并且分配给返回的任何内容c.

当你这样做时a[b] = c,a.__setitem__调用with bcas参数,并且无提示返回的内容将被静默丢弃.

因此,尽管a[b]语法相同,但两个表达式都在做不同的事情.您可以子类化ndarray,重载这两个函数,并使它们的行为不同.正如numpy中的默认情况一样,前者返回一个副本(如果b是数组),但后者会a在适当的位置进行修改.

  • 我认为值得在 numpy 文档中明确指出这样一个事实:即使用作左值时的高级索引也会修改原始数组。 (2认同)