numpy数组,h [:] = h + 1 vs. h = h + 1

时间:2016-03-10 05:35:14

标签: arrays variables numpy global internal

似乎h [:] = h + 1和h = h + 1都为h中的所有元素加1。

但是下面可以找到差异,你能解释一下原因吗?看起来在第二种情况下,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.]]

3 个答案:

答案 0 :(得分:1)

这并不奇怪。我认为您在使用函数h时碰巧命名​​变量fun这一事实让您感到困惑。但是该变量的名称并不重要,并且到达父作用域以修改变量h ...而是将参数传递给{{ 1}}是某个名称,而不是它的副本。因此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.]]

导致 local h = h + 1 (函数作用域内的h)成为 new 名称,该名称是从对于h之前在该函数范围中命名的任何事物的操作h + 1(例如传入的参数)。

由于NumPy数组h的广播操作h + 1会生成 new 数组,因此语句h不会改变h = h + 1。 ..仅仅导致名称h引用新内容(h)。

而在第二个例子中,

h + 1

是指更新由h[:] = h + 1 命名的任何对象的内容

你可以像我一样称它为h,但这并不重要。 "事情[:]"在左侧是切片分配的表示法,它是为NumPy数组实现的,作为切片对象数据的变异。

答案 1 :(得分:1)

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

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

每次向原始内容添加1(在fun的三次调用中),但由于原始内容从未更改,因此它始终是2的数组。

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

会改变输入h。您可以凭借[:]“就地”更改它。因此,在这种情况下,返回的h与输入h相同,这就是您在输出中看到两倍相同的2x2数组的原因。 由于您正在运行此功能三次,因此将其添加1次,导致所有4次。

答案 2 :(得分:1)

区别在于对=陈述的解释。全部是there

案例h=h+1

  

如果目标是标识符(名称):名称绑定到当前本地名称空间中的对象。

案例h[:]=h+1

  

如果目标是订阅:评估引用中的主表达式,并要求序列将分配的对象分配给具有该索引的项目。