python中的变量赋值问题



我正在python中运行以下代码:

w= np.random.rand(3) 
w_old=np.zeros((3,))
while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:
w_old=w
print w
print w_old
w[0]-=eta*dE1i
w[1]-=eta*dE2i
w[2]-=eta*dE3i
print w
print w_old

打印的结果是:

[ 0.22877423  0.59402658  0.16657174]
[ 0.22877423  0.59402658  0.16657174]

[ 0.21625852  0.5573612   0.123111  ]
[ 0.21625852  0.5573612   0.123111  ]

我想知道为什么w_old的值发生了变化?回到while循环的开头后不应该更新吗?我该如何解决这个问题?

只是使用

w_old = w

不复制w,使用=只是告诉python你想要w中存储的任何内容的另一个名称。因此,对w的每次就地更改也会更改w_old。有一篇非常好的博客文章,如果你想了解更多细节 Ned Batchelder:"关于Python名称和值的事实和神话">

您可以显式复制 numpy 数组,例如,使用copy方法:

w_old = w.copy()

为了澄清一下,变量是独立的,因此:

a=5
b=a

如果您更改ab,则可以正常工作。但是列表和字典不能以相同的方式复制,因此:

a=[1,2]
b=a
a[0]=100
print(b[0])

会给你 100 个,因为现在ab是同一个东西,有两个名字。因此,按照使用前的建议

w_old = w.copy()

相反,w_old是一个新列表,而不仅仅是旧列表的另一个名称。

只是为了总结上面的答案,根据python文档

Python 中的赋值语句不复制对象,它们创建 目标和对象之间的绑定。

所以,解决方案是

对于可变或包含可变项的集合,副本是 有时需要,以便可以在不更改 其他。

因此,使用copy()我们可以将代码重写为

import numpy as np
w= np.random.rand(3)
w_old=np.zeros((3,))
while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:
w_old=w.copy()
print(w)
print(w_old)
w[0]-=0.01
w[1]-=0.01
w[2]-=0.01
print(w)
print(w_old)

并得到

[0.79666571 0.82305671 0.41167625]
[0.79666571 0.82305671 0.41167625]

[0.78666571 0.81305671 0.40167625]
[0.79666571 0.82305671 0.41167625]

最新更新