使用Numpy数组和列表进行多重赋值,一个有趣的例子

3
考虑多重赋值x[0],y = y,x[0]。应用于以下四种情况中的每一种,都会得到四个不同的结果。
  • Case 1:

    x = [[1,2], [3,4]]
    y = [5,6]
    

    gives

    x = [[5,6], [3,4]]
    y = [1,2]
    
  • Case 2:

    x = np.array([[1,2], [3,4]])
    y = [5,6]
    

    gives

    x = array([[5,6], [3,4]])
    y = array([5,6])
    
  • Case 3:

    x = [[1,2], [3,4]]
    y = np.array([5,6])
    

    gives

    x = [array([5,6]), [3,4]]
    y = [1,2]
    
  • Case 4:

    x = np.array([[1,2], [3,4]])
    y = np.array([5,6])
    

    gives

    x = array([[5,6], [3,4]])
    y = array([5,6])
    

看起来Python中列表的多重赋值比Numpy数组的多重赋值更加智能(会自动通过一个临时变量进行操作)。

有什么想法吗?

编辑:实际上并不比Numpy数组的多重赋值更智能...


看起来,列表的多重赋值比NumPy数组的多重赋值更加智能(自动通过临时变量)。为什么?当将值分配到NumPy数组时,它会变成NumPy数组的一部分。 - Scimonster
2个回答

5
这里唯一令人惊讶的情况应该是2和4:
x = np.array([[1,2], [3,4]])
y = np.array([5,6])  # or [5, 6]

提供
x = array([[5,6], [3,4]])
y = array([5,6])  # where did the 1 and 2 go?

由于其他人只是在不同数据类型之间进行交换,但保留相同的值。

使用numpy时的不同之处在于x [0]返回一个视图而不是副本。因此,即使在元组赋值中明确写出临时变量也会失败:

temp = x[0]
x[0] = y
y = temp

因为temp是一个视图,它始终与x [0]相同,而不是在那个时间点上x [0]的值的副本。

为了使numpy情况下的代码正常工作,您应该使用x [0],y = y,x [0] .copy()


嗯,是的,2和4是有趣的,但为了完整起见,我把它们全部加上了。 - Gioker

1
x[0],y = y,x[0]

等于
t = x[0]
x[0] = y
y = t

正如@Scimonster所指出的,
当将值赋给Numpy数组时,它会成为Numpy数组的一部分。
因此这是正常行为。

这两个代码块并不真的相等。并没有创建临时变量 t;内部将 yx[0] 推入堆栈,进行反转,然后再弹出并赋值。这两种方法可能导致不同的结果。 - Alex Riley
@ajcr:除了名称“t”被覆盖之外,您能构造出结果确实不同的情况吗? - Eric
@Eric:我想我记错了一些东西,就像我之前遇到的这个问题(现在看来并不涉及临时变量)。我认为应该可以构造一些奇怪的例子,在赋值期间原地改变变量(因此不会改变临时变量),但在我能想出令人信服的东西之前,我将撤回我的先前评论。 - Alex Riley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接