似乎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.]]
答案 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
:
如果目标是订阅:评估引用中的主表达式,并要求序列将分配的对象分配给具有该索引的项目。