【问题标题】:Understanding numpy self-referencing assignment理解 numpy 自引用赋值
【发布时间】:2021-04-03 16:25:12
【问题描述】:

给定一个像这样的自引用分配:

x = np.array(range(5))
y = x[:-1]
print(x, y)
y[0] = 9
print(x, y)
x[1:] = y
print(x, y)

我最终得到以下输出:

[0 1 2 3 4] [0 1 2 3]
[9 1 2 3 4] [9 1 2 3]
[9 9 1 2 3] [9 9 1 2]

有人可以解释一下 numpy 在将其值分配给 x 之前在后台做什么以避免覆盖 y 吗?例如,如果我们将赋值 x[1:] = y 替换为 for 循环,则输出的最后一行是不同的:

x = np.array(range(5))
y = x[:-1]
print(x, y)
y[0] = 9
print(x, y)

for idx in range(1, len(x)):
    x[idx] = y[idx-1]
print(x,y)
[0 1 2 3 4] [0 1 2 3]
[9 1 2 3 4] [9 1 2 3]
[9 9 9 9 9] [9 9 9 9]

一般而言,我可以在更改内存映射 ndarray 的宽度时依赖观察到的行为吗?或者如果 numpy 在分配之前创建视图的副本是没有意义的?

【问题讨论】:

  • Numpy 操作被缓冲,是的

标签: python numpy numpy-ndarray array-broadcasting


【解决方案1】:

所以你有一个简单的一维数组:

In [358]: x = np.array(range(5))
In [359]: x
Out[359]: array([0, 1, 2, 3, 4])
In [360]: x = np.arange(5)
In [361]: x
Out[361]: array([0, 1, 2, 3, 4])

y 是一个视图 - 除了最后一个:

In [362]: y = x[:-1]
In [363]: y
Out[363]: array([0, 1, 2, 3])
In [364]: y[0] = 9
In [365]: x
Out[365]: array([9, 1, 2, 3, 4])

修改y 也会更改x

In [366]: x[1:]
Out[366]: array([1, 2, 3, 4])
In [367]: x[1:] = y
In [368]: x
Out[368]: array([9, 9, 1, 2, 3])

此分配已缓冲。该缓冲的详细信息通常没有记录,但像 np.add.at 这样的函数的文档暗示了这一点。虽然这解释了您看到的行为,但我不知道假设它是否安全。添加副本足够便宜:

x[1:] = y.copy()

add.at 所示,人们通常会被缓冲所困扰,至少在某些指标重复的情况下是这样。我想不出.at 的方式来处理您的迭代案例。


有一种view 复制形式会咬人——例如尝试切换二维数组的行:

In [392]: arr = np.arange(12).reshape(3,4)
In [393]: arr
Out[393]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [394]: arr[0],arr[1] = arr[1],arr[0]
In [395]: arr
Out[395]: 
array([[ 4,  5,  6,  7],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

这里arr[0]arr[1] 之前更新。这种分配适用于列表,但因为arr[i]view,它在列表中失败。

高级索引可以解决这个问题。 RHS 是一个副本,因此不会在分配过程中搞砸。

In [396]: arr = np.arange(12).reshape(3,4)
In [397]: arr[[0,1]] = arr[[1,0]]
In [398]: arr
Out[398]: 
array([[ 4,  5,  6,  7],
       [ 0,  1,  2,  3],
       [ 8,  9, 10, 11]])

我不知道是否可以用您的 1d x 构建这样的示例。

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 2019-10-06
    • 2014-01-08
    • 2014-01-15
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    相关资源
    最近更新 更多