Python 理解numpy自引用赋值

Python 理解numpy自引用赋值,python,numpy,numpy-ndarray,array-broadcasting,Python,Numpy,Numpy Ndarray,Array Broadcasting,给定如下自引用赋值: 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之前,有人能解释一下numpy在引擎盖下做了什么以避免覆盖y?例如,如果我们用For循环替换赋值x[1:]=y,则输

给定如下自引用赋值:

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
之前,有人能解释一下numpy在引擎盖下做了什么以避免覆盖
y
?例如,如果我们用For循环替换赋值
x[1:]=y
,则输出的最后一行是不同的:

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)

一般来说,在更改内存映射阵列的宽度时,我可以依赖观察到的行为吗?或者,如果numpy在赋值之前创建视图的副本,这是毫无意义的吗?

因此您有一个简单的1d数组:

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
的迭代方法


有一种形式的
视图
复制会咬人-例如,尝试切换2d数组的行:

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]
是一个
视图
它在列表中失败

高级索引解决了这个问题。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

缓冲Numpy操作来构造这样一个示例,是的
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]])