3D list和numpy数组之间的解包和赋值奇数

30byixjq  于 2023-06-23  发布在  其他
关注(0)|答案(2)|浏览(107)

我创建一个普通的python列表

a = [[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]]]

现在我想把每个2x2数组的第一行移到前一个2x2数组,把第一行绕回最后一行。我使用以下解包赋值语句:

a[0][0],a[1][0],a[2][0] = a[1][0],a[2][0],a[0][0]

我得到以下,这就是我想要的

print(a)
[[[5, 6], [3, 4]], [[9, 10], [7, 8]], [[1, 2], [11, 12]]]

现在,我做同样的事情,这一次,使用numpy数组

b = np.arange(1,13).reshape((3,2,2))
print(b)
[[[ 1  2]
  [ 3  4]]

 [[ 5  6]
  [ 7  8]]

 [[ 9  10]
  [11 12]]]

移位与之前相同,但使用了numpy索引语法

b[0,0],b[1,0],b[2,0] = b[1,0],b[2,0],b[0,0]
print(b)
[[[ 5  6]
  [ 3  4]]

 [[ 9 10]
  [ 7  8]]

 [[ 5  6]
  [11 12]]]

如您所见,此赋值使第一个和最后一个2x2数组的第一行相同。
你能预料到这种行为差异吗?为什么numpy可以做到这一点,而不是常规的列表类型?numpy赋值如何才能得到与list相同的结果?

cvxl0en2

cvxl0en21#

我的推理方式是,由于b是一个(3,2,2)数组
每一个

b[1,0],b[2,0],b[0,0]

bview。也就是说,有3(2,)个数组,但每个数组使用b data_buffer的不同部分。
在分配期间,b[0,0]被设置为b[1,0]处的值。当它分配给b[2,0]时,B[0,0]现在具有新值[5,6]
我以前见过这种情况。这是数组与列表不完全相同的另一种情况。列表包含指向列表的指针,而数组索引要么生成副本,要么生成视图.视图很方便,但可能会扰乱基于列表/引用的直觉。
幸运的是,数组可以一次分配多个值,所以我们可以这样做:

b[[0,1,2],0] = b[[1,2,0],0]

或具有切片b[:,0]=b[::-1,0]的等效物
前面的问题更多地集中在进行交换的正确方法上,而不是为什么会有区别。因此不会将此标记为重复
Swap slices of Numpy arrays
Row exchange in Numpy

jslywgbw

jslywgbw2#

简单:什么是Python列表?一堆指向对象的指针!当你说a[1][0],a[2][0],a[0][0]时,你(基本上)创建了一个三个对象的元组-指向列表[5,6]的指针,指向列表[9,10]的指针,以及指向列表[1,2]的指针。然后使用a[0][0],a[1][0],a[2][0] = ...将这些指针分配给a中的点
Numpy是不同的。切片表示内存中的位置,而不是指向对象的指针。下面的语句与您的代码相同:当你把b[0,0]赋值给5,6时,b[0,0]引用的内存中的值发生了变化。因此,当你将b[2,0]赋给b[0,0]中的内容时,你会得到5,6

b = np.arange(1,13).reshape((3,2,2))
rhs = b[1,0],b[2,0],b[0,0]
print("before first assign", rhs[2])
b[0,0] = rhs[0]
print("after first assign", rhs[2])
b[1,0] = rhs[1]
b[2,0] = rhs[2]
print(b)
before first assign [1 2]
after first assign [5 6]
[[[ 5  6]
  [ 3  4]]

 [[ 9 10]
  [ 7  8]]

 [[ 5  6]
  [11 12]]]

相关问题