numpy 数组,h[:]=h+1 与 h=h+1

numpy array, h[:]=h+1 vs. h=h+1

好像h[:]=h+1和h=h+1都对h中的所有元素加1。

但是下面可能会发现不同,你能解释一下为什么吗??看起来在第二种情况下,h 不仅作为函数内部变量发生变化,而且还像覆盖全局变量 h...这太令人困惑了... 感谢您的任何输入!

import numpy as np

def fun(h):
    h=h+1
    return h

h=np.zeros((2,2))+1
hI=h.copy()

for i in range(0,3):          
    hI = fun(h) 

print h
print hI
[[ 1.  1.]
 [ 1.  1.]]
[[ 2.  2.]
 [ 2.  2.]]

鉴于

import numpy as np

def fun(h):
    h[:]=h+1
    return h

h=np.zeros((2,2))+1
hI=h.copy()

for i in range(0,3):          
    hI = fun(h) 

print h
print hI

[[ 4.  4.]
 [ 4.  4.]]
[[ 4.  4.]
 [ 4.  4.]]

这并不奇怪。我认为您对在使用函数 fun 时碰巧将变量命名为 h 这一事实感到困惑。但是该变量的名称并不重要,它是 而不是 到达父作用域来修改变量 h ...相反,传递给 fun 是某物的 名称 ,而不是它的副本。因此 fun 内部的突变仍然会影响被命名的对象(在这种情况下,该对象是全局范围的 h 数组)。

为了更清楚地说明这一点,考虑下面的情况,我所做的只是将 fun 内的变量重命名为 z 而不是 h ...发生相同的结果。

In [14]: def fun(z):
   ....:     z[:] = z + 1
   ....:     return z
   ....: 

In [15]: h = np.zeros((2,2)) + 1

In [16]: for i in range(0, 3):
   ....:     hI = fun(h)
   ....:     

In [17]: print h
[[ 4.  4.]
 [ 4.  4.]]

In [18]: print hI
[[ 4.  4.]
 [ 4.  4.]]

在第一个例子中,内部变量没有发生变化。分配

h = h + 1

使 local h(函数范围内的 h)成为 new 名称,从操作 h + 1 创建的对象的名称,用于之前在该函数范围内由 h 命名的任何事物(例如传入的参数)。

由于 NumPy 数组 h 的广播操作 h + 1 产生了 new 数组,所以语句 h = h + 1 没有变异 h ...仅仅导致名称 h 引用新的东西 (h + 1).

而在第二个例子中,

h[:] = h + 1

就是说h命名的任何对象的内容都更新了。

你可以像我一样叫它z[:],没关系。左侧的 "thing[:]" 是切片赋值的表示法,它是为 NumPy 数组实现的,作为切片对象数据的变异。

这个

def fun(h):
    h=h+1
    return h

复制输入参数h。所以输入 h 永远不会改变,即使变量名称恰好相同(您可以使用 f = h + 1; return f 甚至 return h + 1;所有内容都相同)。当您将输入 h 分配给新的 h 时,您只是失去了对输入 h 的引用。 由于输入 h 恰好是您的原始 h(全为 1),因此原始永远不会改变,这就是您在输出中看到的。

您每次都将 1 添加到原件(在对 fun 的三次调用中),但是由于原件永远不会改变,它始终是一个 2 的数组。

这个

def fun(h):
    h[:]=h+1
    return h

确实改变了输入 h。您通过 [:] 更改它 "in place"。所以在这种情况下,返回的 h 与输入 h 相同,这就是为什么您会在输出中看到两次相同的 2x2 数组。
因为你 运行 这个函数三次,所以它被加了三次 1,结果都是 4。

区别在于 = 语句的解释。都是 there :

案例h=h+1

If the target is an identifier (name): the name is bound to the object in the current local namespace.

案例h[:]=h+1

If the target is a subscription: The primary expression in the reference is evaluated,and the sequence is asked to assign the assigned object to its item with that index.