我创建一个普通的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相同的结果?
2条答案
按热度按时间cvxl0en21#
我的推理方式是,由于
b
是一个(3,2,2)数组每一个
是
b
的view
。也就是说,有3(2,)个数组,但每个数组使用b
data_buffer的不同部分。在分配期间,
b[0,0]
被设置为b[1,0]
处的值。当它分配给b[2,0]
时,B[0,0]
现在具有新值[5,6]
。我以前见过这种情况。这是数组与列表不完全相同的另一种情况。列表包含指向列表的指针,而数组索引要么生成副本,要么生成视图.视图很方便,但可能会扰乱基于列表/引用的直觉。
幸运的是,数组可以一次分配多个值,所以我们可以这样做:
或具有切片
b[:,0]=b[::-1,0]
的等效物前面的问题更多地集中在进行交换的正确方法上,而不是为什么会有区别。因此不会将此标记为重复
Swap slices of Numpy arrays
Row exchange in Numpy
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
。