处理numpy数组时赋值运算符中的指针行为?
Posted
技术标签:
【中文标题】处理numpy数组时赋值运算符中的指针行为?【英文标题】:Pointer-like behaviour in assignment operator when dealing with numpy arrays? 【发布时间】:2020-11-03 19:24:33 【问题描述】:我偶然发现了赋值运算符 += 的一些奇怪行为,这完全让我感到困惑。看这段代码sn-p:
import numpy as np
def myalg(data, alpha, beta):
adash=np.zeros(len(data))
a=np.zeros_like(adash)
a_=np.zeros_like(a)
gain=1
count=0
while count<3:
adash=adash+alpha*np.gradient(data)
a_old=a
print( a_old)
#a+=alpha* (np.gradient(adash)+ alpha* data)
a=a+alpha* (np.gradient(adash)+ alpha* data)
print( a_old)
a/=1+alpha*beta
#a=a/(1+alpha*beta)
print( a_old)
a_=2*a-a_old
gain=la.norm(a-a_old)
count+=1
print(a)
print(a_)
print(adash)
print(gain)
data=np.arange(6)
myalg(data, alpha=0.4, beta=0.25)
我原以为将“cmets”之一交换为上述替代行时不会发生任何变化。虽然a
-array 在每种情况下确实是相同的,但代码确实改变了a_old
:
选择a=a+...
时,a_old
保持不变,无论下面选择a/=
或a=a/...
中的哪一个。
在a+=
987654329 @时,a_old
的行为a
。所以print(a_old)
每次被调用时都会产生a
的值,直到a
被明确地分配一个新值(例如a= a/...
,而不是像+=, -=, *=, /=
这样的赋值运算符)。
那么为什么数组会发生这种情况?
编辑:我知道它是如何发生的,但我不明白为什么会发生这种情况。 为什么这种行为不会发生,例如整数还是浮点数?
【问题讨论】:
您可以使用a_old = aprint(a_old)
,但此时a_old
尚未定义。这应该会导致 UnboundLocalError。还有什么是aprint
?请注意,a += ...
会就地修改数组,而a = a + ...
会创建一个新副本。
我在您的代码中看不到任何 a*=...
或 a=a*...
。描述不清楚。
y=x
不进行复制。 y
引用与 x
相同的对象。如果y
发生突变,您也会看到x
的变化。数字是不可变的,数组(和列表)是可变的。
【参考方案1】:
请查看每行的 cmets 以了解行为不同的原因(注意:缩进是为了清楚起见,而不是为了编码):
#This points to `a`
a_old=a
print(a_old)
#This changes `a` inplace so `a_old` will change too
a+=alpha* (np.gradient(adash)+ alpha* data)
#This creates a NEW `a`, therefore `a_old` will not change
a=a+alpha* (np.gradient(adash)+ alpha* data)
print(a_old)
#if you have used `a+=..` this changes `a` inplace again and so `a_old`
#if you have used `a=a+..` this changes the NEW `a` and NOT the `a_old`
a/=1+alpha*beta
#this creates yet another NEWER `a`
#and hence `a_old` does not change beyond the LAST print
a=a/(1+alpha*beta)
print(a_old)
【讨论】:
对 */-混淆感到抱歉,为了清楚起见,我对其进行了编辑。我已经意识到导致这种行为的过程,但是我不明白为什么其他对象(如浮点数/整数)不是这种情况...... 因为 float/int 数据类型不是指针,它总是在原地改变。虽然数组对象是指针,并且当您更改指针时,对象也会更改(指向内存中的不同位置)。另外,请查看***.com/help/someone-answers,了解如何接受关于 SO 的答案。谢谢 @Ehsan,我认为您的意思是浮点/整数数据类型 从不 就地更改。只有可变类型(如数组)可以就地更改。请注意,对于要就地更改的变量,该变量的id()
(即它在内存中的位置)保持不变,而变量的内容会发生变化。以上是关于处理numpy数组时赋值运算符中的指针行为?的主要内容,如果未能解决你的问题,请参考以下文章